Peripheral interconnect redo, vol 2 (split()) (#2418)

* Replace peripheral connection conversions with split

* Constrain Flex conversions
This commit is contained in:
Dániel Buga 2024-11-04 12:29:28 +01:00 committed by GitHub
parent 177db100fb
commit 0c86740418
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 354 additions and 217 deletions

View File

@ -26,6 +26,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `DmaDescriptor` is now `Send` (#2456)
- `into_async` and `into_blocking` functions for most peripherals (#2430)
- API mode type parameter (currently always `Blocking`) to `master::Spi` and `slave::Spi` (#2430)
- `gpio::{GpioPin, AnyPin, Flex, Output, OutputOpenDrain}::split()` to obtain peripheral interconnect signals. (#2418)
- `gpio::Input::{split(), into_peripheral_output()}` when used with output pins. (#2418)
- `gpio::Output::peripheral_input()` (#2418)
### Changed
@ -42,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- SPI interrupt listening is now only available in Blocking mode. The `set_interrupt_handler` is available via `InterruptConfigurable` (#2442)
- Allow users to create DMA `Preparation`s (#2455)
- The `rmt::asynch::RxChannelAsync` and `rmt::asynch::TxChannelAsync` traits have been moved to `rmt` (#2430)
- Calling `AnyPin::output_signals` on an input-only pin (ESP32 GPIO 34-39) will now result in a panic. (#2418)
### Fixed

View File

@ -194,7 +194,8 @@ You can now listen/unlisten multiple interrupt bits at once:
-uart0.listen_at_cmd();
-uart0.listen_rx_fifo_full();
+uart0.listen(UartInterrupt::AtCmd | UartConterrupt::RxFifoFull);
```˛
```
## Circular DMA transfer's `available` returns `Result<usize, DmaError>` now
In case of any error you should drop the transfer and restart it.
@ -211,3 +212,21 @@ In case of any error you should drop the transfer and restart it.
+ },
+ };
```
## Removed `peripheral_input` and `into_peripheral_output` from GPIO pin types
Creating peripheral interconnect signals now consume the GPIO pin used for the connection.
The previous signal function have been replaced by `split`. This change affects the following APIs:
- `GpioPin`
- `AnyPin`
```diff
-let input_signal = gpioN.peripheral_input();
-let output_signal = gpioN.into_peripheral_output();
+let (input_signal, output_signal) = gpioN.split();
```
`into_peripheral_output`, `split` (for output pins only) and `peripheral_input` have been added to
the GPIO drivers (`Input`, `Output`, `OutputOpenDrain` and `Flex`) instead.

View File

@ -54,9 +54,6 @@ impl PeripheralOutput for OutputConnection {}
/// A configurable input signal between a peripheral and a GPIO pin.
///
/// Obtained by calling [`super::GpioPin::peripheral_input()`],
/// [`super::Flex::peripheral_input()`] or [`super::Input::peripheral_input()`].
///
/// Multiple input signals can be connected to one pin.
pub struct InputSignal {
pin: AnyPin,
@ -188,10 +185,6 @@ impl InputSignal {
/// A configurable output signal between a peripheral and a GPIO pin.
///
/// Obtained by calling [`super::GpioPin::into_peripheral_output()`],
/// [`super::Flex::into_peripheral_output()`] or
/// [`super::Output::into_peripheral_output()`].
///
/// Multiple pins can be connected to one output signal.
pub struct OutputSignal {
pin: AnyPin,
@ -441,9 +434,9 @@ where
P: InputPin,
{
fn from(input: P) -> Self {
Self(InputConnectionInner::Input(
input.degrade().peripheral_input(),
))
Self(InputConnectionInner::Input(InputSignal::new(
input.degrade(),
)))
}
}
@ -534,9 +527,9 @@ where
P: OutputPin,
{
fn from(input: P) -> Self {
Self(OutputConnectionInner::Output(
input.degrade().into_peripheral_output(),
))
Self(OutputConnectionInner::Output(OutputSignal::new(
input.degrade(),
)))
}
}

View File

@ -723,13 +723,15 @@ where
Self
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
/// Split the pin into an input and output signal.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
interconnect::InputSignal::new(self.degrade_pin(private::Internal))
/// Peripheral signals allow connecting peripherals together without using
/// external hardware.
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
(
interconnect::InputSignal::new(self.degrade_pin(private::Internal)),
interconnect::OutputSignal::new(self.degrade_pin(private::Internal)),
)
}
}
@ -777,21 +779,6 @@ where
impl<const GPIONUM: u8> private::Sealed for GpioPin<GPIONUM> {}
impl<const GPIONUM: u8> GpioPin<GPIONUM>
where
Self: OutputPin,
{
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
interconnect::OutputSignal::new(self.degrade_pin(private::Internal))
}
}
/// General Purpose Input/Output driver
pub struct Io {
_io_mux: IO_MUX,
@ -1151,20 +1138,41 @@ where
/// Create GPIO output driver for a [GpioPin] with the provided level
#[inline]
pub fn new_typed(pin: impl Peripheral<P = P> + 'd, initial_output: Level) -> Self {
let pin = Flex::new_typed(pin);
Self::new_inner(pin, initial_output)
}
fn new_inner(mut pin: Flex<'d, P>, initial_output: Level) -> Self {
pin.pin
.set_output_high(initial_output.into(), private::Internal);
let mut pin = Flex::new_typed(pin);
pin.set_level(initial_output);
pin.set_as_output();
Self { pin }
}
/// Split the pin into an input and output signal.
///
/// Peripheral signals allow connecting peripherals together without using
/// external hardware.
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
self.pin.split()
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
self.pin.peripheral_input()
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
self.pin.into_peripheral_output()
}
/// Set the output as high.
#[inline]
pub fn set_high(&mut self) {
@ -1212,16 +1220,6 @@ where
pub fn set_drive_strength(&mut self, strength: DriveStrength) {
self.pin.set_drive_strength(strength);
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
self.pin.into_peripheral_output()
}
}
/// GPIO input driver.
@ -1262,6 +1260,15 @@ where
Self { pin }
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
self.pin.peripheral_input()
}
/// Get whether the pin input level is high.
#[inline]
pub fn is_high(&self) -> bool {
@ -1311,14 +1318,28 @@ where
pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) {
self.pin.wakeup_enable(enable, event);
}
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
impl<P> Input<'_, P>
where
P: InputPin + OutputPin,
{
/// Split the pin into an input and output signal.
///
/// The input signal can be passed to peripherals in place of an input pin.
/// Peripheral signals allow connecting peripherals together without using
/// external hardware.
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
self.pin.split()
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
self.pin.peripheral_input()
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
self.pin.into_peripheral_output()
}
}
@ -1365,6 +1386,33 @@ where
Self { pin }
}
/// Split the pin into an input and output signal.
///
/// Peripheral signals allow connecting peripherals together without using
/// external hardware.
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
self.pin.split()
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
self.pin.peripheral_input()
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
self.pin.into_peripheral_output()
}
/// Get whether the pin input level is high.
#[inline]
pub fn is_high(&self) -> bool {
@ -1441,16 +1489,6 @@ where
pub fn set_drive_strength(&mut self, strength: DriveStrength) {
self.pin.set_drive_strength(strength);
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
self.pin.into_peripheral_output()
}
}
/// Flexible pin driver.
@ -1487,6 +1525,15 @@ where
crate::into_ref!(pin);
Self { pin }
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
self.pin.degrade_pin(private::Internal).split().0
}
}
impl<P> Flex<'_, P>
@ -1577,15 +1624,6 @@ where
pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) {
self.listen_with_options(event.into(), false, false, enable);
}
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
///
/// The input signal can be passed to peripherals in place of an input pin.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
interconnect::InputSignal::new(self.pin.degrade_pin(private::Internal))
}
}
impl<P> Flex<'_, P>
@ -1646,6 +1684,20 @@ where
self.pin.set_drive_strength(strength, private::Internal);
}
/// Set the GPIO to open-drain mode.
pub fn set_as_open_drain(&mut self, pull: Pull) {
self.pin.set_to_open_drain_output(private::Internal);
self.pin.pull_direction(pull, private::Internal);
}
/// Split the pin into an input and output signal.
///
/// Peripheral signals allow connecting peripherals together without using
/// external hardware.
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
self.pin.degrade_pin(private::Internal).split()
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
@ -1653,18 +1705,7 @@ where
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
interconnect::OutputSignal::new(self.pin.degrade_pin(private::Internal))
}
}
impl<P> Flex<'_, P>
where
P: InputPin + OutputPin,
{
/// Set the GPIO to open-drain mode.
pub fn set_as_open_drain(&mut self, pull: Pull) {
self.pin.set_to_open_drain_output(private::Internal);
self.pin.pull_direction(pull, private::Internal);
self.split().1
}
}
@ -1674,24 +1715,13 @@ pub(crate) mod internal {
impl private::Sealed for AnyPin {}
impl AnyPin {
/// Returns a peripheral [input][interconnect::InputSignal] connected to
/// this pin.
/// Split the pin into an input and output signal.
///
/// The input signal can be passed to peripherals in place of an input
/// pin.
/// Peripheral signals allow connecting peripherals together without
/// using external hardware.
#[inline]
pub fn peripheral_input(&self) -> interconnect::InputSignal {
handle_gpio_input!(&self.0, target, { target.peripheral_input() })
}
/// Turns the pin object into a peripheral
/// [output][interconnect::OutputSignal].
///
/// The output signal can be passed to peripherals in place of an output
/// pin.
#[inline]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
handle_gpio_output!(self.0, target, { target.into_peripheral_output() })
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
handle_gpio_input!(self.0, target, { target.split() })
}
}
@ -1717,7 +1747,7 @@ pub(crate) mod internal {
}
fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)] {
handle_gpio_input!(&self.0, target, {
handle_gpio_output!(&self.0, target, {
Pin::output_signals(target, private::Internal)
})
}
@ -1736,7 +1766,74 @@ pub(crate) mod internal {
}
impl InputPin for AnyPin {}
impl OutputPin for AnyPin {}
// Need to forward these one by one because not all pins support all functions.
impl OutputPin for AnyPin {
fn init_output(
&mut self,
alternate: AlternateFunction,
open_drain: bool,
_: private::Internal,
) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::init_output(target, alternate, open_drain, private::Internal)
})
}
fn set_to_open_drain_output(&mut self, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::set_to_open_drain_output(target, private::Internal)
})
}
fn set_to_push_pull_output(&mut self, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::set_to_push_pull_output(target, private::Internal)
})
}
fn set_output_high(&mut self, high: bool, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::set_output_high(target, high, private::Internal)
})
}
fn set_drive_strength(&mut self, strength: DriveStrength, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::set_drive_strength(target, strength, private::Internal)
})
}
fn enable_open_drain(&mut self, on: bool, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::enable_open_drain(target, on, private::Internal)
})
}
fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::enable_output_in_sleep_mode(target, on, private::Internal)
})
}
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::internal_pull_up_in_sleep_mode(target, on, private::Internal)
})
}
fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
handle_gpio_output!(&mut self.0, target, {
OutputPin::internal_pull_down_in_sleep_mode(target, on, private::Internal)
})
}
fn is_set_high(&self, _: private::Internal) -> bool {
handle_gpio_output!(&self.0, target, {
OutputPin::is_set_high(target, private::Internal)
})
}
}
#[cfg(any(xtensa, esp32c2, esp32c3, esp32c6))]
impl RtcPin for AnyPin {

View File

@ -98,12 +98,12 @@
//!
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//!
//! let rx = io.pins.gpio2.peripheral_input().inverted();
//! let tx = io.pins.gpio1.into_peripheral_output().inverted();
//! let (rx, _) = io.pins.gpio2.split();
//! let (_, tx) = io.pins.gpio1.split();
//! let mut uart1 = Uart::new(
//! peripherals.UART1,
//! rx,
//! tx,
//! rx.inverted(),
//! tx.inverted(),
//! ).unwrap();
//! # }
//! ```

View File

@ -94,11 +94,11 @@ async fn main(spawner: Spawner) {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let tx_pin = io.pins.gpio2;
// let rx_pin = io.pins.gpio0; // Uncomment if you want to use an external transceiver.
// Without an external transceiver, we only need a single line between the two MCUs.
let rx_pin = tx_pin.peripheral_input(); // Comment this line if you want to use an external transceiver.
let (rx_pin, tx_pin) = io.pins.gpio2.split();
// Use these if you want to use an external transceiver:
// let tx_pin = io.pins.gpio2;
// let rx_pin = io.pins.gpio0;
// The speed of the bus.
const TWAI_BAUDRATE: twai::BaudRate = twai::BaudRate::B125K;

View File

@ -49,18 +49,22 @@ fn main() -> ! {
println!("setup channel 0");
let ch0 = &u0.channel0;
let pin_a = Input::new(io.pins.gpio4, Pull::Up);
let pin_b = Input::new(io.pins.gpio5, Pull::Up);
ch0.set_ctrl_signal(pin_a.peripheral_input());
ch0.set_edge_signal(pin_b.peripheral_input());
let (input_a, _) = pin_a.split();
let (input_b, _) = pin_b.split();
ch0.set_ctrl_signal(input_a.clone());
ch0.set_edge_signal(input_b.clone());
ch0.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);
ch0.set_input_mode(channel::EdgeMode::Increment, channel::EdgeMode::Decrement);
println!("setup channel 1");
let ch1 = &u0.channel1;
ch1.set_ctrl_signal(pin_b.peripheral_input());
ch1.set_edge_signal(pin_a.peripheral_input());
ch1.set_ctrl_signal(input_b);
ch1.set_edge_signal(input_a);
ch1.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);
ch1.set_input_mode(channel::EdgeMode::Decrement, channel::EdgeMode::Increment);

View File

@ -42,11 +42,11 @@ fn main() -> ! {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let tx_pin = io.pins.gpio2;
// let rx_pin = io.pins.gpio0; // Uncomment if you want to use an external transceiver.
// Without an external transceiver, we only need a single line between the two MCUs.
let rx_pin = tx_pin.peripheral_input(); // Comment this line if you want to use an external transceiver.
let (rx_pin, tx_pin) = io.pins.gpio2.split();
// Use these if you want to use an external transceiver:
// let tx_pin = io.pins.gpio2;
// let rx_pin = io.pins.gpio0;
// The speed of the bus.
const TWAI_BAUDRATE: twai::BaudRate = twai::BaudRate::B125K;

View File

@ -151,7 +151,7 @@ mod tests {
let (_, dout) = hil_test::common_test_pins!(ctx.io);
let din = dout.peripheral_input();
let (din, dout) = dout.split();
let i2s_tx = i2s
.i2s_tx
@ -205,7 +205,7 @@ mod tests {
let (_, dout) = hil_test::common_test_pins!(ctx.io);
let din = dout.peripheral_input();
let (din, dout) = dout.split();
let mut i2s_tx = i2s
.i2s_tx
@ -347,7 +347,8 @@ mod tests {
);
let (_, dout) = hil_test::common_test_pins!(ctx.io);
let din = dout.peripheral_input();
let (din, dout) = dout.split();
let mut i2s_rx = i2s
.i2s_rx

View File

@ -102,20 +102,14 @@ mod tests {
// issue with configuring pins as outputs after inputs have been sorted
// out. See https://github.com/esp-rs/esp-hal/pull/2173#issue-2529323702
let cs_signal = ctx.io.pins.gpio8;
let unit0_signal = ctx.io.pins.gpio11;
let unit1_signal = ctx.io.pins.gpio12;
let unit2_signal = ctx.io.pins.gpio16;
let unit3_signal = ctx.io.pins.gpio17;
let (unit_ctrl, cs_signal) = ctx.io.pins.gpio8.split();
let (unit0_input, unit0_signal) = ctx.io.pins.gpio11.split();
let (unit1_input, unit1_signal) = ctx.io.pins.gpio12.split();
let (unit2_input, unit2_signal) = ctx.io.pins.gpio16.split();
let (unit3_input, unit3_signal) = ctx.io.pins.gpio17.split();
let pcnt = ctx.pcnt;
let unit_ctrl = cs_signal.peripheral_input();
let unit0_input = unit0_signal.peripheral_input();
let unit1_input = unit1_signal.peripheral_input();
let unit2_input = unit2_signal.peripheral_input();
let unit3_input = unit3_signal.peripheral_input();
pcnt.unit0
.channel0
.set_ctrl_mode(CtrlMode::Keep, CtrlMode::Disable);
@ -219,20 +213,14 @@ mod tests {
// issue with configuring pins as outputs after inputs have been sorted
// out. See https://github.com/esp-rs/esp-hal/pull/2173#issue-2529323702
let cs_signal = ctx.io.pins.gpio8;
let unit0_signal = ctx.io.pins.gpio11;
let unit1_signal = ctx.io.pins.gpio12;
let unit2_signal = ctx.io.pins.gpio16;
let unit3_signal = ctx.io.pins.gpio17;
let (unit_ctrl, cs_signal) = ctx.io.pins.gpio8.split();
let (unit0_input, unit0_signal) = ctx.io.pins.gpio11.split();
let (unit1_input, unit1_signal) = ctx.io.pins.gpio12.split();
let (unit2_input, unit2_signal) = ctx.io.pins.gpio16.split();
let (unit3_input, unit3_signal) = ctx.io.pins.gpio17.split();
let pcnt = ctx.pcnt;
let unit_ctrl = cs_signal.peripheral_input();
let unit0_input = unit0_signal.peripheral_input();
let unit1_input = unit1_signal.peripheral_input();
let unit2_input = unit2_signal.peripheral_input();
let unit3_input = unit3_signal.peripheral_input();
pcnt.unit0
.channel0
.set_ctrl_mode(CtrlMode::Keep, CtrlMode::Disable);

View File

@ -8,7 +8,11 @@
use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits};
use esp_hal::{
dma::{ChannelCreator, Dma, DmaPriority},
gpio::{interconnect::InputSignal, AnyPin, Io, NoPin},
gpio::{
interconnect::{InputSignal, OutputSignal},
Io,
NoPin,
},
parl_io::{
BitPackOrder,
ClkOutPin,
@ -30,8 +34,8 @@ use hil_test as _;
struct Context {
parl_io: PARL_IO,
dma_channel: ChannelCreator<0>,
clock: AnyPin,
valid: AnyPin,
clock: OutputSignal,
valid: OutputSignal,
clock_loopback: InputSignal,
valid_loopback: InputSignal,
pcnt_unit: Unit<'static, 0>,
@ -50,10 +54,9 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (clock, _) = hil_test::common_test_pins!(io);
let valid = io.pins.gpio0.degrade();
let clock_loopback = clock.peripheral_input();
let valid_loopback = valid.peripheral_input();
let clock = clock.degrade();
let valid = hil_test::unconnected_pin!(io);
let (clock_loopback, clock) = clock.split();
let (valid_loopback, valid) = valid.split();
let pcnt = Pcnt::new(peripherals.PCNT);
let pcnt_unit = pcnt.unit0;
let dma = Dma::new(peripherals.DMA);

View File

@ -10,7 +10,11 @@
use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits};
use esp_hal::{
dma::{ChannelCreator, Dma, DmaPriority},
gpio::{interconnect::InputSignal, AnyPin, Io, NoPin},
gpio::{
interconnect::{InputSignal, OutputSignal},
Io,
NoPin,
},
parl_io::{
BitPackOrder,
ClkOutPin,
@ -32,8 +36,8 @@ use hil_test as _;
struct Context {
parl_io: PARL_IO,
dma_channel: ChannelCreator<0>,
clock: AnyPin,
valid: AnyPin,
clock: OutputSignal,
valid: OutputSignal,
clock_loopback: InputSignal,
valid_loopback: InputSignal,
pcnt_unit: Unit<'static, 0>,
@ -52,10 +56,9 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (clock, _) = hil_test::common_test_pins!(io);
let valid = io.pins.gpio0.degrade();
let clock_loopback = clock.peripheral_input();
let valid_loopback = valid.peripheral_input();
let clock = clock.degrade();
let valid = hil_test::unconnected_pin!(io);
let (clock_loopback, clock) = clock.split();
let (valid_loopback, valid) = valid.split();
let pcnt = Pcnt::new(peripherals.PCNT);
let pcnt_unit = pcnt.unit0;
let dma = Dma::new(peripherals.DMA);

View File

@ -335,7 +335,9 @@ mod tests {
let unit0 = pcnt.unit0;
let unit1 = pcnt.unit1;
unit0.channel0.set_edge_signal(mosi.peripheral_input());
let (mosi_loopback, mosi) = mosi.split();
unit0.channel0.set_edge_signal(mosi_loopback);
unit0
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -359,12 +361,15 @@ mod tests {
let unit0 = pcnt.unit0;
let unit1 = pcnt.unit1;
unit0.channel0.set_edge_signal(mosi.peripheral_input());
let (mosi_loopback, mosi) = mosi.split();
let (gpio_loopback, gpio) = gpio.split();
unit0.channel0.set_edge_signal(mosi_loopback);
unit0
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
unit1.channel0.set_edge_signal(gpio.peripheral_input());
unit1.channel0.set_edge_signal(gpio_loopback);
unit1
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -389,12 +394,15 @@ mod tests {
let unit0 = pcnt.unit0;
let unit1 = pcnt.unit1;
unit0.channel0.set_edge_signal(mosi.peripheral_input());
let (mosi_loopback, mosi) = mosi.split();
let (gpio_loopback, gpio) = gpio.split();
unit0.channel0.set_edge_signal(mosi_loopback);
unit0
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
unit1.channel0.set_edge_signal(gpio.peripheral_input());
unit1.channel0.set_edge_signal(gpio_loopback);
unit1
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -419,12 +427,15 @@ mod tests {
let unit0 = pcnt.unit0;
let unit1 = pcnt.unit1;
unit0.channel0.set_edge_signal(mosi.peripheral_input());
let (mosi_loopback, mosi) = mosi.split();
let (gpio_loopback, gpio) = gpio.split();
unit0.channel0.set_edge_signal(mosi_loopback);
unit0
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
unit1.channel0.set_edge_signal(gpio.peripheral_input());
unit1.channel0.set_edge_signal(gpio_loopback);
unit1
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);

View File

@ -73,7 +73,7 @@ mod tests {
}
#[cfg(pcnt)]
let mosi_loopback_pcnt = mosi.peripheral_input();
let (mosi_loopback_pcnt, mosi) = mosi.split();
// Need to set miso first so that mosi can overwrite the
// output connection (because we are using the same pin to loop back)
let spi = Spi::new(peripherals.SPI2, 10000.kHz(), SpiMode::Mode0)

View File

@ -50,7 +50,7 @@ mod tests {
}
}
let mosi_loopback = mosi.peripheral_input();
let (mosi_loopback, mosi) = mosi.split();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)

View File

@ -62,7 +62,7 @@ mod tests {
let dma_channel = dma.channel0;
let mosi_loopback = mosi.peripheral_input();
let (mosi_loopback, mosi) = mosi.split();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)

View File

@ -11,7 +11,10 @@
use esp_hal::{
dma::{Dma, DmaPriority},
dma_buffers,
gpio::{interconnect::InputSignal, Io, Level, Output},
gpio::{
interconnect::{InputSignal, OutputSignal},
Io,
},
spi::{slave::Spi, SpiMode},
Blocking,
};
@ -32,19 +35,32 @@ struct Context {
}
struct BitbangSpi {
sclk: Output<'static>,
mosi: Output<'static>,
sclk: OutputSignal,
mosi: OutputSignal,
miso: InputSignal,
cs: Output<'static>,
cs: OutputSignal,
}
impl BitbangSpi {
fn new(
sclk: Output<'static>,
mosi: Output<'static>,
miso: InputSignal,
cs: Output<'static>,
mut sclk: OutputSignal,
mut mosi: OutputSignal,
mut miso: InputSignal,
mut cs: OutputSignal,
) -> Self {
// TODO remove this (#2273)
// FIXME: devise a public API for signals
miso.enable_input(true, unsafe { esp_hal::Internal::conjure() });
mosi.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
mosi.enable_output(true, unsafe { esp_hal::Internal::conjure() });
cs.set_output_high(true, unsafe { esp_hal::Internal::conjure() });
cs.enable_output(true, unsafe { esp_hal::Internal::conjure() });
sclk.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
sclk.enable_output(true, unsafe { esp_hal::Internal::conjure() });
Self {
sclk,
mosi,
@ -54,22 +70,29 @@ impl BitbangSpi {
}
fn assert_cs(&mut self) {
self.sclk.set_level(Level::Low);
self.cs.set_level(Level::Low);
self.sclk
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
self.cs
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
}
fn deassert_cs(&mut self) {
self.sclk.set_level(Level::Low);
self.cs.set_level(Level::High);
self.sclk
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
self.cs
.set_output_high(true, unsafe { esp_hal::Internal::conjure() });
}
// Mode 1, so sampled on the rising edge and set on the falling edge.
fn shift_bit(&mut self, bit: bool) -> bool {
self.mosi.set_level(Level::from(bit));
self.sclk.set_level(Level::High);
self.mosi
.set_output_high(bit, unsafe { esp_hal::Internal::conjure() });
self.sclk
.set_output_high(true, unsafe { esp_hal::Internal::conjure() });
let miso = self.miso.get_level().into();
self.sclk.set_level(Level::Low);
self.sclk
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
miso
}
@ -105,7 +128,7 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (mosi_pin, miso_pin) = hil_test::i2c_pins!(io);
let (sclk_pin, sclk_gpio) = hil_test::common_test_pins!(io);
let (sclk_pin, _) = hil_test::common_test_pins!(io);
let cs_pin = hil_test::unconnected_pin!(io);
let dma = Dma::new(peripherals.DMA);
@ -118,30 +141,22 @@ mod tests {
}
}
let cs = cs_pin.peripheral_input();
let mosi = mosi_pin.peripheral_input();
let mut miso = miso_pin.peripheral_input();
let sclk_signal = sclk_pin.peripheral_input();
let (cs, cs_pin) = cs_pin.split();
let (mosi, mosi_pin) = mosi_pin.split();
let (miso, miso_pin) = miso_pin.split();
let (sclk_signal, sclk_pin) = sclk_pin.split();
let mosi_gpio = Output::new(mosi_pin, Level::Low);
let cs_gpio = Output::new(cs_pin, Level::High);
let sclk_gpio = Output::new(sclk_gpio, Level::Low);
let spi = Spi::new(
Context {
spi: Spi::new(
peripherals.SPI2,
sclk_signal,
mosi,
miso_pin,
cs,
SpiMode::Mode1,
);
miso.enable_input(true, unsafe { esp_hal::Internal::conjure() });
Context {
spi,
),
bitbang_spi: BitbangSpi::new(sclk_pin, mosi_pin, miso, cs_pin),
dma_channel,
bitbang_spi: BitbangSpi::new(sclk_gpio, mosi_gpio, miso, cs_gpio),
}
}

View File

@ -32,10 +32,12 @@ mod tests {
let (loopback_pin, _) = hil_test::common_test_pins!(io);
let (rx, tx) = loopback_pin.split();
let mut config = twai::TwaiConfiguration::new(
peripherals.TWAI0,
loopback_pin.peripheral_input(),
loopback_pin,
rx,
tx,
twai::BaudRate::B1000K,
TwaiMode::SelfTest,
);

View File

@ -32,12 +32,9 @@ mod tests {
let (_, pin) = hil_test::common_test_pins!(io);
let uart = Uart::new(
peripherals.UART1,
pin.peripheral_input(),
pin.into_peripheral_output(),
)
.unwrap();
let (rx, tx) = pin.split();
let uart = Uart::new(peripherals.UART1, rx, tx).unwrap();
Context { uart }
}