mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00
Peripheral interconnect redo, vol 2 (split()
) (#2418)
* Replace peripheral connection conversions with split * Constrain Flex conversions
This commit is contained in:
parent
177db100fb
commit
0c86740418
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
//! # }
|
||||
//! ```
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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 }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user