Interconnect: force signals through GPIO matrix if split (#2419)
* Allow splitting off of gpio drivers * Extract and correct low level connection bits * Add Input/OutputSignal::connect_to * Remove unnecessary public API * Fix typos * Remove unused private methods * Add separate Direct signals that do bypass the GPIO matrix * Do not disable stage input * Clean up spi_slave test * Constrain to static Flex * Improve docs * Separate input_enable and open_drain parameters * Link to the chapter * Changelog * Clarify
This commit is contained in:
parent
ccb3a1ba40
commit
4c5be2c907
@ -53,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Calling `AnyPin::output_signals` on an input-only pin (ESP32 GPIO 34-39) will now result in a panic. (#2418)
|
- Calling `AnyPin::output_signals` on an input-only pin (ESP32 GPIO 34-39) will now result in a panic. (#2418)
|
||||||
- UART configuration types have been moved to `esp_hal::uart` (#2449)
|
- UART configuration types have been moved to `esp_hal::uart` (#2449)
|
||||||
- `spi::master::Spi::new()` no longer takes `frequency` and `mode` as a parameter. (#2448)
|
- `spi::master::Spi::new()` no longer takes `frequency` and `mode` as a parameter. (#2448)
|
||||||
|
- Peripheral interconnections via GPIO pins now use the GPIO matrix. (#2419)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,9 @@ use crate::{
|
|||||||
self,
|
self,
|
||||||
AlternateFunction,
|
AlternateFunction,
|
||||||
AnyPin,
|
AnyPin,
|
||||||
|
Flex,
|
||||||
InputPin,
|
InputPin,
|
||||||
|
InputSignalType,
|
||||||
Level,
|
Level,
|
||||||
NoPin,
|
NoPin,
|
||||||
OutputPin,
|
OutputPin,
|
||||||
@ -34,24 +36,179 @@ pub trait PeripheralInput: Into<InputConnection> + 'static {}
|
|||||||
/// [`PeripheralInput`] as arguments instead of pin types.
|
/// [`PeripheralInput`] as arguments instead of pin types.
|
||||||
pub trait PeripheralOutput: Into<OutputConnection> + 'static {}
|
pub trait PeripheralOutput: Into<OutputConnection> + 'static {}
|
||||||
|
|
||||||
|
// Pins
|
||||||
impl<P: InputPin> PeripheralInput for P {}
|
impl<P: InputPin> PeripheralInput for P {}
|
||||||
impl<P: OutputPin> PeripheralOutput for P {}
|
impl<P: OutputPin> PeripheralOutput for P {}
|
||||||
|
|
||||||
impl PeripheralInput for InputSignal {}
|
// Pin drivers
|
||||||
impl PeripheralInput for OutputSignal {}
|
impl<P: InputPin> PeripheralInput for Flex<'static, P> {}
|
||||||
impl PeripheralOutput for OutputSignal {}
|
impl<P: OutputPin> PeripheralOutput for Flex<'static, P> {}
|
||||||
|
|
||||||
|
// Placeholders
|
||||||
impl PeripheralInput for NoPin {}
|
impl PeripheralInput for NoPin {}
|
||||||
impl PeripheralOutput for NoPin {}
|
impl PeripheralOutput for NoPin {}
|
||||||
|
|
||||||
impl PeripheralInput for Level {}
|
impl PeripheralInput for Level {}
|
||||||
impl PeripheralOutput for Level {}
|
impl PeripheralOutput for Level {}
|
||||||
|
|
||||||
impl PeripheralInput for InputConnection {}
|
// Split signals
|
||||||
|
impl PeripheralInput for InputSignal {}
|
||||||
|
impl PeripheralInput for OutputSignal {}
|
||||||
|
impl PeripheralOutput for OutputSignal {}
|
||||||
|
|
||||||
|
// Type-erased signals
|
||||||
|
impl PeripheralInput for InputConnection {}
|
||||||
impl PeripheralInput for OutputConnection {}
|
impl PeripheralInput for OutputConnection {}
|
||||||
impl PeripheralOutput for OutputConnection {}
|
impl PeripheralOutput for OutputConnection {}
|
||||||
|
|
||||||
|
impl gpio::InputSignal {
|
||||||
|
fn can_use_gpio_matrix(self) -> bool {
|
||||||
|
self as InputSignalType <= INPUT_SIGNAL_MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connects a peripheral input signal to a GPIO or a constant level.
|
||||||
|
///
|
||||||
|
/// Note that connecting multiple GPIOs to a single peripheral input is not
|
||||||
|
/// possible and the previous connection will be replaced.
|
||||||
|
///
|
||||||
|
/// Also note that a peripheral input must always be connected to something,
|
||||||
|
/// so if you want to disconnect it from GPIOs, you should connect it to a
|
||||||
|
/// constant level.
|
||||||
|
#[inline]
|
||||||
|
pub fn connect_to(self, pin: impl Peripheral<P = impl PeripheralInput>) {
|
||||||
|
crate::into_mapped_ref!(pin);
|
||||||
|
|
||||||
|
pin.connect_input_to_peripheral(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl gpio::OutputSignal {
|
||||||
|
fn can_use_gpio_matrix(self) -> bool {
|
||||||
|
self as OutputSignalType <= OUTPUT_SIGNAL_MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connects a peripheral output signal to a GPIO.
|
||||||
|
///
|
||||||
|
/// Note that connecting multiple output signals to a single GPIO is not
|
||||||
|
/// possible and the previous connection will be replaced.
|
||||||
|
///
|
||||||
|
/// Also note that it is possible to connect a peripheral output signal to
|
||||||
|
/// multiple GPIOs, and old connections will not be cleared automatically.
|
||||||
|
#[inline]
|
||||||
|
pub fn connect_to(self, pin: impl Peripheral<P = impl PeripheralOutput>) {
|
||||||
|
crate::into_mapped_ref!(pin);
|
||||||
|
|
||||||
|
pin.connect_peripheral_to_output(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disconnects a peripheral output signal from a GPIO.
|
||||||
|
#[inline]
|
||||||
|
pub fn disconnect_from(self, pin: impl Peripheral<P = impl PeripheralOutput>) {
|
||||||
|
crate::into_mapped_ref!(pin);
|
||||||
|
|
||||||
|
pin.disconnect_from_peripheral_output(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connects a peripheral input (`signal`, e.g. SPI MISO) to a GPIO or a
|
||||||
|
/// constant level (`input`).
|
||||||
|
///
|
||||||
|
/// - `signal`: The input signal to connect to the pin
|
||||||
|
/// - `input`: The GPIO (or constant level) number to connect to the input
|
||||||
|
/// signal.
|
||||||
|
/// - `invert`: Configures whether or not to invert the input value
|
||||||
|
/// - `use_gpio_matrix`: true to route through the GPIO matrix
|
||||||
|
pub(crate) fn connect_input_signal(
|
||||||
|
signal: gpio::InputSignal,
|
||||||
|
input: u8,
|
||||||
|
invert: bool,
|
||||||
|
use_gpio_matrix: bool,
|
||||||
|
) {
|
||||||
|
assert!(
|
||||||
|
signal.can_use_gpio_matrix() || !use_gpio_matrix,
|
||||||
|
"{:?} cannot be routed through the GPIO matrix",
|
||||||
|
signal
|
||||||
|
);
|
||||||
|
unsafe { GPIO::steal() }
|
||||||
|
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
||||||
|
.write(|w| unsafe {
|
||||||
|
w.sel().bit(use_gpio_matrix);
|
||||||
|
w.in_inv_sel().bit(invert);
|
||||||
|
w.in_sel().bits(input) // Connect to GPIO or constant level
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_pin_to_input_signal(
|
||||||
|
pin: &mut AnyPin,
|
||||||
|
signal: gpio::InputSignal,
|
||||||
|
is_inverted: bool,
|
||||||
|
force_gpio: bool,
|
||||||
|
) {
|
||||||
|
let af = if is_inverted || force_gpio {
|
||||||
|
GPIO_FUNCTION
|
||||||
|
} else {
|
||||||
|
pin.input_signals(private::Internal)
|
||||||
|
.iter()
|
||||||
|
.find(|(_af, s)| *s == signal)
|
||||||
|
.map(|(af, _)| *af)
|
||||||
|
.unwrap_or(GPIO_FUNCTION)
|
||||||
|
};
|
||||||
|
|
||||||
|
pin.set_alternate_function(af, private::Internal);
|
||||||
|
|
||||||
|
connect_input_signal(signal, pin.number(), is_inverted, af == GPIO_FUNCTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_peripheral_to_output(
|
||||||
|
pin: &mut AnyPin,
|
||||||
|
signal: gpio::OutputSignal,
|
||||||
|
is_inverted: bool,
|
||||||
|
force_gpio: bool,
|
||||||
|
peripheral_control_output_enable: bool,
|
||||||
|
invert_output_enable: bool,
|
||||||
|
) {
|
||||||
|
let af = if is_inverted || force_gpio {
|
||||||
|
GPIO_FUNCTION
|
||||||
|
} else {
|
||||||
|
pin.output_signals(private::Internal)
|
||||||
|
.iter()
|
||||||
|
.find(|(_af, s)| *s == signal)
|
||||||
|
.map(|(af, _)| *af)
|
||||||
|
.unwrap_or(GPIO_FUNCTION)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
signal.can_use_gpio_matrix() || af != GPIO_FUNCTION,
|
||||||
|
"{:?} cannot be routed through the GPIO matrix",
|
||||||
|
signal
|
||||||
|
);
|
||||||
|
|
||||||
|
pin.set_alternate_function(af, private::Internal);
|
||||||
|
|
||||||
|
// Inlined because output signals can only be connected to pins or nothing, so
|
||||||
|
// there is no other user.
|
||||||
|
unsafe { GPIO::steal() }
|
||||||
|
.func_out_sel_cfg(pin.number() as usize)
|
||||||
|
.write(|w| unsafe {
|
||||||
|
if af == GPIO_FUNCTION {
|
||||||
|
// Ignored if the signal is not routed through the GPIO matrix - alternate
|
||||||
|
// function selects peripheral signal directly.
|
||||||
|
w.out_sel().bits(signal as _);
|
||||||
|
w.inv_sel().bit(is_inverted);
|
||||||
|
}
|
||||||
|
w.oen_sel().bit(!peripheral_control_output_enable);
|
||||||
|
w.oen_inv_sel().bit(invert_output_enable)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disconnect_peripheral_output_from_pin(pin: &mut AnyPin, signal: gpio::OutputSignal) {
|
||||||
|
pin.set_alternate_function(GPIO_FUNCTION, private::Internal);
|
||||||
|
|
||||||
|
unsafe { GPIO::steal() }
|
||||||
|
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
||||||
|
.write(|w| w.sel().clear_bit());
|
||||||
|
}
|
||||||
|
|
||||||
/// A configurable input signal between a peripheral and a GPIO pin.
|
/// A configurable input signal between a peripheral and a GPIO pin.
|
||||||
///
|
///
|
||||||
/// Multiple input signals can be connected to one pin.
|
/// Multiple input signals can be connected to one pin.
|
||||||
@ -69,6 +226,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P> From<Flex<'static, P>> for InputSignal
|
||||||
|
where
|
||||||
|
P: InputPin,
|
||||||
|
{
|
||||||
|
fn from(input: Flex<'static, P>) -> Self {
|
||||||
|
Self::new(input.degrade())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clone for InputSignal {
|
impl Clone for InputSignal {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -113,7 +279,7 @@ impl InputSignal {
|
|||||||
self.is_inverted = !self.is_inverted;
|
self.is_inverted = !self.is_inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumed the signal and returns a new one that inverts the peripheral's
|
/// Consumes the signal and returns a new one that inverts the peripheral's
|
||||||
/// input signal.
|
/// input signal.
|
||||||
///
|
///
|
||||||
/// Calling this function multiple times toggles the setting.
|
/// Calling this function multiple times toggles the setting.
|
||||||
@ -122,64 +288,13 @@ impl InputSignal {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - signal: The input signal to connect to the pin
|
|
||||||
/// - invert: Configures whether or not to invert the input value
|
|
||||||
/// - input: The GPIO number to connect to the input signal
|
|
||||||
fn connect(&self, signal: usize, invert: bool, input: u8) {
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_in_sel_cfg(signal - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| unsafe {
|
|
||||||
w.sel().set_bit();
|
|
||||||
w.in_inv_sel().bit(invert);
|
|
||||||
w.in_sel().bits(input)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect the pin to a peripheral input signal.
|
/// Connect the pin to a peripheral input signal.
|
||||||
///
|
///
|
||||||
/// Since there can only be one input signal connected to a peripheral at a
|
/// Since there can only be one input signal connected to a peripheral at a
|
||||||
/// time, this function will disconnect any previously connected input
|
/// time, this function will disconnect any previously connected input
|
||||||
/// signals.
|
/// signals.
|
||||||
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal, _: private::Internal) {
|
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal) {
|
||||||
let signal_nr = signal as usize;
|
connect_pin_to_input_signal(&mut self.pin, signal, self.is_inverted, true);
|
||||||
|
|
||||||
let af = if self.is_inverted {
|
|
||||||
GPIO_FUNCTION
|
|
||||||
} else {
|
|
||||||
self.input_signals(private::Internal)
|
|
||||||
.iter()
|
|
||||||
.find(|(_af, s)| *s == signal)
|
|
||||||
.map(|(af, _)| *af)
|
|
||||||
.unwrap_or(GPIO_FUNCTION)
|
|
||||||
};
|
|
||||||
|
|
||||||
if af == GPIO_FUNCTION && signal_nr > INPUT_SIGNAL_MAX as usize {
|
|
||||||
panic!("Cannot connect GPIO to this peripheral");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.pin.set_alternate_function(af, private::Internal);
|
|
||||||
|
|
||||||
if signal_nr <= INPUT_SIGNAL_MAX as usize {
|
|
||||||
self.connect(signal_nr, self.is_inverted, self.pin.number());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove this pin from a connected peripheral input.
|
|
||||||
///
|
|
||||||
/// Clears the entry in the GPIO matrix / Io mux that associates this input
|
|
||||||
/// pin with the given [input `signal`](`InputSignal`). Any other
|
|
||||||
/// connected signals remain intact.
|
|
||||||
fn disconnect_input_from_peripheral(
|
|
||||||
&mut self,
|
|
||||||
signal: gpio::InputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
self.pin
|
|
||||||
.set_alternate_function(GPIO_FUNCTION, private::Internal);
|
|
||||||
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| w.sel().clear_bit());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate::delegate! {
|
delegate::delegate! {
|
||||||
@ -190,7 +305,44 @@ impl InputSignal {
|
|||||||
pub fn init_input(&self, pull: Pull, _internal: private::Internal);
|
pub fn init_input(&self, pull: Pull, _internal: private::Internal);
|
||||||
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
||||||
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A limited, private version of [InputSignal] that allows bypassing the GPIO
|
||||||
|
/// matrix. This is only usable when the GPIO pin connected to the signal is not
|
||||||
|
/// split.
|
||||||
|
struct DirectInputSignal {
|
||||||
|
pin: AnyPin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for DirectInputSignal {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self::new(unsafe { self.pin.clone_unchecked() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectInputSignal {
|
||||||
|
pub(crate) fn new(pin: AnyPin) -> Self {
|
||||||
|
Self { pin }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect the pin to a peripheral input signal.
|
||||||
|
///
|
||||||
|
/// Since there can only be one input signal connected to a peripheral at a
|
||||||
|
/// time, this function will disconnect any previously connected input
|
||||||
|
/// signals.
|
||||||
|
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal) {
|
||||||
|
connect_pin_to_input_signal(&mut self.pin, signal, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.pin {
|
||||||
|
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
|
||||||
|
fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)];
|
||||||
|
fn init_input(&self, pull: Pull, _internal: private::Internal);
|
||||||
|
fn is_input_high(&self, _internal: private::Internal) -> bool;
|
||||||
|
fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,6 +364,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P> From<Flex<'static, P>> for OutputSignal
|
||||||
|
where
|
||||||
|
P: OutputPin,
|
||||||
|
{
|
||||||
|
fn from(input: Flex<'static, P>) -> Self {
|
||||||
|
Self::new(input.degrade())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Peripheral for OutputSignal {
|
impl Peripheral for OutputSignal {
|
||||||
type P = Self;
|
type P = Self;
|
||||||
|
|
||||||
@ -245,7 +406,7 @@ impl OutputSignal {
|
|||||||
self.is_inverted = !self.is_inverted;
|
self.is_inverted = !self.is_inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumed the signal and returns a new one that inverts the peripheral's
|
/// Consumes the signal and returns a new one that inverts the peripheral's
|
||||||
/// output signal.
|
/// output signal.
|
||||||
///
|
///
|
||||||
/// Calling this function multiple times toggles the setting.
|
/// Calling this function multiple times toggles the setting.
|
||||||
@ -254,139 +415,18 @@ impl OutputSignal {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - signal: The input signal to connect to the pin
|
|
||||||
/// - invert: Configures whether or not to invert the input value
|
|
||||||
/// - input: The GPIO number to connect to the input signal
|
|
||||||
fn connect_input(&self, signal: usize, invert: bool, input: u8) {
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_in_sel_cfg(signal - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| unsafe {
|
|
||||||
w.sel().set_bit();
|
|
||||||
w.in_inv_sel().bit(invert);
|
|
||||||
w.in_sel().bits(input)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// - signal: The output signal to connect to the pin
|
|
||||||
/// - invert: Configures whether or not to invert the output value
|
|
||||||
/// - invert_enable: Configures whether or not to invert the output enable
|
|
||||||
/// signal
|
|
||||||
/// - enable_from_gpio: Configures to select the source of output enable
|
|
||||||
/// signal.
|
|
||||||
/// - false: Use output enable signal from peripheral
|
|
||||||
/// - true: Force the output enable signal to be sourced from bit n of
|
|
||||||
/// GPIO_ENABLE_REG
|
|
||||||
/// - output: The GPIO number to connect to the output signal
|
|
||||||
fn connect_output(
|
|
||||||
&self,
|
|
||||||
signal: OutputSignalType,
|
|
||||||
invert: bool,
|
|
||||||
invert_enable: bool,
|
|
||||||
enable_from_gpio: bool,
|
|
||||||
output: u8,
|
|
||||||
) {
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_out_sel_cfg(output as usize)
|
|
||||||
.modify(|_, w| unsafe {
|
|
||||||
w.out_sel().bits(signal);
|
|
||||||
w.inv_sel().bit(invert);
|
|
||||||
w.oen_sel().bit(enable_from_gpio);
|
|
||||||
w.oen_inv_sel().bit(invert_enable)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect the pin to a peripheral input signal.
|
|
||||||
///
|
|
||||||
/// Since there can only be one signal connected to a peripheral input at a
|
|
||||||
/// time, this function will disconnect any previously connected input
|
|
||||||
/// signals.
|
|
||||||
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal, _: private::Internal) {
|
|
||||||
let signal_nr = signal as usize;
|
|
||||||
|
|
||||||
let af = if self.is_inverted {
|
|
||||||
GPIO_FUNCTION
|
|
||||||
} else {
|
|
||||||
self.input_signals(private::Internal)
|
|
||||||
.iter()
|
|
||||||
.find(|(_af, s)| *s == signal)
|
|
||||||
.map(|(af, _)| *af)
|
|
||||||
.unwrap_or(GPIO_FUNCTION)
|
|
||||||
};
|
|
||||||
|
|
||||||
if af == GPIO_FUNCTION && signal_nr > INPUT_SIGNAL_MAX as usize {
|
|
||||||
panic!("Cannot connect GPIO to this peripheral");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.pin.set_alternate_function(af, private::Internal);
|
|
||||||
|
|
||||||
if signal_nr <= INPUT_SIGNAL_MAX as usize {
|
|
||||||
self.connect_input(signal_nr, self.is_inverted, self.pin.number());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove this pin from a connected peripheral input.
|
|
||||||
///
|
|
||||||
/// Clears the entry in the GPIO matrix / Io mux that associates this input
|
|
||||||
/// pin with the given [input `signal`](`InputSignal`). Any other
|
|
||||||
/// connected signals remain intact.
|
|
||||||
fn disconnect_input_from_peripheral(
|
|
||||||
&mut self,
|
|
||||||
signal: gpio::InputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
self.pin
|
|
||||||
.set_alternate_function(GPIO_FUNCTION, private::Internal);
|
|
||||||
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| w.sel().clear_bit());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect the pin to a peripheral output signal.
|
/// Connect the pin to a peripheral output signal.
|
||||||
fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal, _: private::Internal) {
|
fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal) {
|
||||||
let af = if self.is_inverted {
|
connect_peripheral_to_output(&mut self.pin, signal, self.is_inverted, true, true, false);
|
||||||
GPIO_FUNCTION
|
|
||||||
} else {
|
|
||||||
self.output_signals(private::Internal)
|
|
||||||
.iter()
|
|
||||||
.find(|(_af, s)| *s == signal)
|
|
||||||
.map(|(af, _)| *af)
|
|
||||||
.unwrap_or(GPIO_FUNCTION)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.pin.set_alternate_function(af, private::Internal);
|
|
||||||
|
|
||||||
let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize {
|
|
||||||
signal as OutputSignalType
|
|
||||||
} else {
|
|
||||||
OUTPUT_SIGNAL_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
self.connect_output(
|
|
||||||
clipped_signal,
|
|
||||||
self.is_inverted,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
self.pin.number(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove this output pin from a connected [signal](`OutputSignal`).
|
/// Remove this output pin from a connected [signal](`gpio::OutputSignal`).
|
||||||
///
|
///
|
||||||
/// Clears the entry in the GPIO matrix / Io mux that associates this output
|
/// Clears the entry in the GPIO matrix / Io mux that associates this output
|
||||||
/// pin with a previously connected [signal](`OutputSignal`). Any other
|
/// pin with a previously connected [signal](`gpio::OutputSignal`). Any
|
||||||
/// outputs connected to the peripheral remain intact.
|
/// other outputs connected to the peripheral remain intact.
|
||||||
fn disconnect_from_peripheral_output(
|
fn disconnect_from_peripheral_output(&mut self, signal: gpio::OutputSignal) {
|
||||||
&mut self,
|
disconnect_peripheral_output_from_pin(&mut self.pin, signal);
|
||||||
signal: gpio::OutputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
self.pin
|
|
||||||
.set_alternate_function(GPIO_FUNCTION, private::Internal);
|
|
||||||
|
|
||||||
unsafe { GPIO::steal() }
|
|
||||||
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| w.sel().clear_bit());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate::delegate! {
|
delegate::delegate! {
|
||||||
@ -397,7 +437,6 @@ impl OutputSignal {
|
|||||||
pub fn init_input(&self, pull: Pull, _internal: private::Internal);
|
pub fn init_input(&self, pull: Pull, _internal: private::Internal);
|
||||||
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
||||||
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
|
||||||
|
|
||||||
pub fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)];
|
pub fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)];
|
||||||
pub fn set_to_open_drain_output(&mut self, _internal: private::Internal);
|
pub fn set_to_open_drain_output(&mut self, _internal: private::Internal);
|
||||||
@ -406,7 +445,6 @@ impl OutputSignal {
|
|||||||
pub fn set_output_high(&mut self, on: bool, _internal: private::Internal);
|
pub fn set_output_high(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
|
pub fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
|
||||||
pub fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
|
||||||
pub fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
pub fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
pub fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn is_set_high(&self, _internal: private::Internal) -> bool;
|
pub fn is_set_high(&self, _internal: private::Internal) -> bool;
|
||||||
@ -414,13 +452,62 @@ impl OutputSignal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A limited, private version of [OutputSignal] that allows bypassing the GPIO
|
||||||
|
/// matrix. This is only usable when the GPIO pin connected to the signal is not
|
||||||
|
/// split.
|
||||||
|
struct DirectOutputSignal {
|
||||||
|
pin: AnyPin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectOutputSignal {
|
||||||
|
pub(crate) fn new(pin: AnyPin) -> Self {
|
||||||
|
Self { pin }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect the pin to a peripheral output signal.
|
||||||
|
fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal) {
|
||||||
|
connect_peripheral_to_output(&mut self.pin, signal, false, false, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove this output pin from a connected [signal](`gpio::OutputSignal`).
|
||||||
|
///
|
||||||
|
/// Clears the entry in the GPIO matrix / Io mux that associates this output
|
||||||
|
/// pin with a previously connected [signal](`gpio::OutputSignal`). Any
|
||||||
|
/// other outputs connected to the peripheral remain intact.
|
||||||
|
fn disconnect_from_peripheral_output(&mut self, signal: gpio::OutputSignal) {
|
||||||
|
disconnect_peripheral_output_from_pin(&mut self.pin, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.pin {
|
||||||
|
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
|
||||||
|
fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)];
|
||||||
|
fn init_input(&self, pull: Pull, _internal: private::Internal);
|
||||||
|
fn is_input_high(&self, _internal: private::Internal) -> bool;
|
||||||
|
fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
|
||||||
|
fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)];
|
||||||
|
fn set_to_open_drain_output(&mut self, _internal: private::Internal);
|
||||||
|
fn set_to_push_pull_output(&mut self, _internal: private::Internal);
|
||||||
|
fn enable_output(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
fn set_output_high(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
|
||||||
|
fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
|
fn is_set_high(&self, _internal: private::Internal) -> bool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum InputConnectionInner {
|
enum InputConnectionInner {
|
||||||
Input(InputSignal),
|
Input(InputSignal),
|
||||||
|
DirectInput(DirectInputSignal),
|
||||||
Constant(Level),
|
Constant(Level),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type-erased peripheral input signal connection.
|
/// A peripheral input signal connection.
|
||||||
///
|
///
|
||||||
/// This is mainly intended for internal use, but it can be used to connect
|
/// This is mainly intended for internal use, but it can be used to connect
|
||||||
/// peripherals within the MCU without external hardware.
|
/// peripherals within the MCU without external hardware.
|
||||||
@ -471,15 +558,33 @@ impl From<OutputSignal> for InputConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<DirectOutputSignal> for InputConnection {
|
||||||
|
fn from(output_signal: DirectOutputSignal) -> Self {
|
||||||
|
Self(InputConnectionInner::DirectInput(DirectInputSignal::new(
|
||||||
|
output_signal.pin,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<OutputConnection> for InputConnection {
|
impl From<OutputConnection> for InputConnection {
|
||||||
fn from(conn: OutputConnection) -> Self {
|
fn from(conn: OutputConnection) -> Self {
|
||||||
match conn.0 {
|
match conn.0 {
|
||||||
OutputConnectionInner::Output(inner) => inner.into(),
|
OutputConnectionInner::Output(inner) => inner.into(),
|
||||||
|
OutputConnectionInner::DirectOutput(inner) => inner.into(),
|
||||||
OutputConnectionInner::Constant(inner) => inner.into(),
|
OutputConnectionInner::Constant(inner) => inner.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P> From<Flex<'static, P>> for InputConnection
|
||||||
|
where
|
||||||
|
P: InputPin,
|
||||||
|
{
|
||||||
|
fn from(pin: Flex<'static, P>) -> Self {
|
||||||
|
pin.peripheral_input().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Sealed for InputConnection {}
|
impl Sealed for InputConnection {}
|
||||||
|
|
||||||
impl InputConnection {
|
impl InputConnection {
|
||||||
@ -487,6 +592,7 @@ impl InputConnection {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
to match &self.0 {
|
to match &self.0 {
|
||||||
InputConnectionInner::Input(pin) => pin,
|
InputConnectionInner::Input(pin) => pin,
|
||||||
|
InputConnectionInner::DirectInput(pin) => pin,
|
||||||
InputConnectionInner::Constant(level) => level,
|
InputConnectionInner::Constant(level) => level,
|
||||||
} {
|
} {
|
||||||
pub fn pull_direction(&self, pull: Pull, _internal: private::Internal);
|
pub fn pull_direction(&self, pull: Pull, _internal: private::Internal);
|
||||||
@ -498,22 +604,22 @@ impl InputConnection {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
to match &mut self.0 {
|
to match &mut self.0 {
|
||||||
InputConnectionInner::Input(pin) => pin,
|
InputConnectionInner::Input(pin) => pin,
|
||||||
|
InputConnectionInner::DirectInput(pin) => pin,
|
||||||
InputConnectionInner::Constant(level) => level,
|
InputConnectionInner::Constant(level) => level,
|
||||||
} {
|
} {
|
||||||
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal);
|
||||||
pub fn connect_input_to_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
|
|
||||||
pub fn disconnect_input_from_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OutputConnectionInner {
|
enum OutputConnectionInner {
|
||||||
Output(OutputSignal),
|
Output(OutputSignal),
|
||||||
|
DirectOutput(DirectOutputSignal),
|
||||||
Constant(Level),
|
Constant(Level),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type-erased peripheral (input and) output signal connection.
|
/// A peripheral (input and) output signal connection.
|
||||||
///
|
///
|
||||||
/// This is mainly intended for internal use, but it can be used to connect
|
/// This is mainly intended for internal use, but it can be used to connect
|
||||||
/// peripherals within the MCU without external hardware.
|
/// peripherals within the MCU without external hardware.
|
||||||
@ -527,6 +633,9 @@ impl Peripheral for OutputConnection {
|
|||||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||||
match self {
|
match self {
|
||||||
Self(OutputConnectionInner::Output(signal)) => Self::from(signal.clone_unchecked()),
|
Self(OutputConnectionInner::Output(signal)) => Self::from(signal.clone_unchecked()),
|
||||||
|
Self(OutputConnectionInner::DirectOutput(signal)) => {
|
||||||
|
Self::from(DirectOutputSignal::new(signal.pin.clone_unchecked()))
|
||||||
|
}
|
||||||
Self(OutputConnectionInner::Constant(level)) => Self::from(*level),
|
Self(OutputConnectionInner::Constant(level)) => Self::from(*level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,54 +668,55 @@ impl From<OutputSignal> for OutputConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<P> From<Flex<'static, P>> for OutputConnection
|
||||||
|
where
|
||||||
|
P: OutputPin,
|
||||||
|
{
|
||||||
|
fn from(pin: Flex<'static, P>) -> Self {
|
||||||
|
pin.into_peripheral_output().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DirectOutputSignal> for OutputConnection {
|
||||||
|
fn from(signal: DirectOutputSignal) -> Self {
|
||||||
|
Self(OutputConnectionInner::DirectOutput(signal))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl OutputConnection {
|
impl OutputConnection {
|
||||||
delegate::delegate! {
|
delegate::delegate! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
to match &self.0 {
|
to match &self.0 {
|
||||||
OutputConnectionInner::Output(pin) => pin,
|
OutputConnectionInner::Output(pin) => pin,
|
||||||
|
OutputConnectionInner::DirectOutput(pin) => pin,
|
||||||
OutputConnectionInner::Constant(level) => level,
|
OutputConnectionInner::Constant(level) => level,
|
||||||
} {
|
} {
|
||||||
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
pub fn is_input_high(&self, _internal: private::Internal) -> bool;
|
||||||
pub fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)];
|
pub fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)];
|
||||||
|
|
||||||
|
pub fn is_set_high(&self, _internal: private::Internal) -> bool;
|
||||||
|
pub fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)];
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
to match &mut self.0 {
|
to match &mut self.0 {
|
||||||
OutputConnectionInner::Output(pin) => pin,
|
OutputConnectionInner::Output(pin) => pin,
|
||||||
|
OutputConnectionInner::DirectOutput(pin) => pin,
|
||||||
OutputConnectionInner::Constant(level) => level,
|
OutputConnectionInner::Constant(level) => level,
|
||||||
} {
|
} {
|
||||||
pub fn pull_direction(&mut self, pull: Pull, _internal: private::Internal);
|
pub fn pull_direction(&mut self, pull: Pull, _internal: private::Internal);
|
||||||
pub fn init_input(&mut self, pull: Pull, _internal: private::Internal);
|
pub fn init_input(&mut self, pull: Pull, _internal: private::Internal);
|
||||||
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_input(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
|
||||||
pub fn connect_input_to_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
|
|
||||||
pub fn disconnect_input_from_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
to match &self.0 {
|
|
||||||
OutputConnectionInner::Output(pin) => pin,
|
|
||||||
OutputConnectionInner::Constant(level) => level,
|
|
||||||
} {
|
|
||||||
pub fn is_set_high(&self, _internal: private::Internal) -> bool;
|
|
||||||
pub fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)];
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
to match &mut self.0 {
|
|
||||||
OutputConnectionInner::Output(pin) => pin,
|
|
||||||
OutputConnectionInner::Constant(level) => level,
|
|
||||||
} {
|
|
||||||
pub fn set_to_open_drain_output(&mut self, _internal: private::Internal);
|
pub fn set_to_open_drain_output(&mut self, _internal: private::Internal);
|
||||||
pub fn set_to_push_pull_output(&mut self, _internal: private::Internal);
|
pub fn set_to_push_pull_output(&mut self, _internal: private::Internal);
|
||||||
pub fn enable_output(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_output(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn set_output_high(&mut self, on: bool, _internal: private::Internal);
|
pub fn set_output_high(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
|
pub fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
|
||||||
pub fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
|
pub fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
|
||||||
pub fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
pub fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
pub fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
|
||||||
pub fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal, _internal: private::Internal);
|
fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal);
|
||||||
pub fn disconnect_from_peripheral_output(&mut self, signal: gpio::OutputSignal, _internal: private::Internal);
|
fn disconnect_from_peripheral_output(&mut self, signal: gpio::OutputSignal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,39 +1,49 @@
|
|||||||
//! # General Purpose I/Os (GPIO)
|
//! # General Purpose Input/Output (GPIO)
|
||||||
//!
|
//!
|
||||||
//! ## Overview
|
//! ## Overview
|
||||||
//!
|
//!
|
||||||
//! Each pin can be used as a general-purpose I/O, or be connected to one or
|
//! Each pin can be used as a general-purpose I/O, or be connected to one or
|
||||||
//! more internal peripheral signals.
|
//! more internal peripheral signals.
|
||||||
|
#![cfg_attr(
|
||||||
|
soc_etm,
|
||||||
|
doc = "The GPIO pins also provide tasks and events via the ETM interconnect system. For more information, see the [etm] module."
|
||||||
|
)]
|
||||||
|
#![doc = ""]
|
||||||
|
//! ## Working with pins
|
||||||
//!
|
//!
|
||||||
//! ## Configuration
|
//! Before use, the GPIO module must be initialized by creating an instance of
|
||||||
|
//! the [`Io`] struct. This struct provides access to the pins on the chip.
|
||||||
//!
|
//!
|
||||||
//! This driver supports various operations on GPIO pins, including setting the
|
//! The [`Io`] struct can also be used to configure the interrupt handler for
|
||||||
//! pin mode, direction, and manipulating the pin state (setting high/low,
|
//! GPIO interrupts. For more information, see the
|
||||||
//! toggling). It provides an interface to interact with GPIO pins on ESP chips,
|
//! [`Io::set_interrupt_handler`].
|
||||||
//! allowing developers to control and read the state of the pins.
|
|
||||||
//!
|
//!
|
||||||
//! ## Usage
|
//! The pins are accessible via [`Io::pins`]. These pins can then be passed to
|
||||||
|
//! peripherals (such as SPI, UART, I2C, etc.), to pin drivers or can be
|
||||||
|
//! [`GpioPin::split`] into peripheral signals.
|
||||||
//!
|
//!
|
||||||
//! This module also implements a number of traits from [embedded-hal] to
|
//! Each pin is a different type initially. Internally, `esp-hal` will often
|
||||||
//! provide a common interface for GPIO pins.
|
//! erase their types automatically, but they can also be converted into
|
||||||
|
//! [`AnyPin`] manually by calling [`Pin::degrade`].
|
||||||
//!
|
//!
|
||||||
//! To get access to the pins, you first need to convert them into a HAL
|
//! Pin drivers can be created using [`Flex::new`], [`Input::new`],
|
||||||
//! designed struct from the pac struct `GPIO` and `IO_MUX` using [`Io::new`].
|
//! [`Output::new`] and [`OutputOpenDrain::new`]. If you need the pin drivers to
|
||||||
|
//! carry the type of the pin, you can use the [`Flex::new_typed`],
|
||||||
|
//! [`Input::new_typed`], [`Output::new_typed`], and
|
||||||
|
//! [`OutputOpenDrain::new_typed`] functions.
|
||||||
//!
|
//!
|
||||||
//! ### Pin Types
|
//! ## GPIO interconnect
|
||||||
//!
|
//!
|
||||||
//! - [Input] pins can be used as digital inputs.
|
//! Sometimes you may want to connect peripherals together without using
|
||||||
//! - [Output] and [OutputOpenDrain] pins can be used as digital outputs.
|
//! external hardware. The [`interconnect`] module provides tools to achieve
|
||||||
//! - [Flex] pin is a pin that can be used as an input and output pin.
|
//! this using GPIO pins.
|
||||||
//! - [AnyPin] is a type-erased GPIO pin with support for inverted signalling.
|
|
||||||
//! - [NoPin] is a useful for cases where peripheral driver requires a pin, but
|
|
||||||
//! real pin cannot be used.
|
|
||||||
//!
|
//!
|
||||||
//! ### GPIO interconnect
|
//! To obtain peripheral signals, use the [`GpioPin::split`] method to split a
|
||||||
//!
|
//! pin into an input and output signal. Alternatively, you may use
|
||||||
//! Each GPIO can be connected to one output signal and any number of input
|
//! [`Flex::split`], [`Flex::into_peripheral_output`],
|
||||||
//! signals. This allows connections inside of the MCU without allocating and
|
//! [`Flex::peripheral_input`], and similar methods to split a pin driver into
|
||||||
//! connecting multiple pins for loopback functionality.
|
//! an input and output signal. You can then pass these signals to the
|
||||||
|
//! peripheral drivers similar to how you would pass a pin.
|
||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
@ -49,14 +59,14 @@
|
|||||||
//!
|
//!
|
||||||
//! ### Blink an LED
|
//! ### Blink an LED
|
||||||
//!
|
//!
|
||||||
//! See the [Blinky] section of the crate documentation.
|
//! See the [Blinky][crate#blinky] section of the crate documentation.
|
||||||
|
//!
|
||||||
|
//! ### Inverting peripheral signals
|
||||||
//!
|
//!
|
||||||
//! ### Inverting a signal using `AnyPin`
|
|
||||||
//! See the [Inverting TX and RX Pins] example of the UART documentation.
|
//! See the [Inverting TX and RX Pins] example of the UART documentation.
|
||||||
//!
|
//!
|
||||||
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
|
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
|
||||||
//! [Blinky]: ../index.html#blinky
|
//! [Inverting TX and RX Pins]: crate::uart#inverting-rx-and-tx-pins
|
||||||
//! [Inverting TX and RX Pins]: ../uart/index.html#inverting-tx-and-rx-pins
|
|
||||||
|
|
||||||
use portable_atomic::{AtomicPtr, Ordering};
|
use portable_atomic::{AtomicPtr, Ordering};
|
||||||
use procmacros::ram;
|
use procmacros::ram;
|
||||||
@ -217,9 +227,13 @@ pub enum DriveStrength {
|
|||||||
///
|
///
|
||||||
/// GPIO pins can be configured for various functions, such as GPIO
|
/// GPIO pins can be configured for various functions, such as GPIO
|
||||||
/// or being directly connected to a peripheral's signal like UART, SPI, etc.
|
/// or being directly connected to a peripheral's signal like UART, SPI, etc.
|
||||||
/// The `AlternateFunction` enum allows to select one of several functions that
|
/// The `AlternateFunction` enum allows selecting one of several functions that
|
||||||
/// a pin can perform, rather than using it as a general-purpose input or
|
/// a pin can perform, rather than using it as a general-purpose input or
|
||||||
/// output.
|
/// output.
|
||||||
|
///
|
||||||
|
/// The different variants correspond to different functionality depending on
|
||||||
|
/// the chip and the specific pin. For more information, refer to your chip's
|
||||||
|
#[doc = crate::trm_markdown_link!("iomuxgpio")]
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum AlternateFunction {
|
pub enum AlternateFunction {
|
||||||
@ -384,12 +398,6 @@ pub trait InputPin: Pin + Into<AnyPin> + 'static {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable input in sleep mode for the pin
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn enable_input_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
|
|
||||||
get_io_mux_reg(self.number()).modify(|_, w| w.mcu_ie().bit(on));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current state of the input
|
/// The current state of the input
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn is_input_high(&self, _: private::Internal) -> bool {
|
fn is_input_high(&self, _: private::Internal) -> bool {
|
||||||
@ -405,6 +413,7 @@ pub trait OutputPin: Pin + Into<AnyPin> + 'static {
|
|||||||
&mut self,
|
&mut self,
|
||||||
alternate: AlternateFunction,
|
alternate: AlternateFunction,
|
||||||
open_drain: bool,
|
open_drain: bool,
|
||||||
|
input_enable: Option<bool>,
|
||||||
_: private::Internal,
|
_: private::Internal,
|
||||||
) {
|
) {
|
||||||
self.enable_output(true, private::Internal);
|
self.enable_output(true, private::Internal);
|
||||||
@ -422,7 +431,9 @@ pub trait OutputPin: Pin + Into<AnyPin> + 'static {
|
|||||||
|
|
||||||
get_io_mux_reg(self.number()).modify(|_, w| unsafe {
|
get_io_mux_reg(self.number()).modify(|_, w| unsafe {
|
||||||
w.mcu_sel().bits(alternate as u8);
|
w.mcu_sel().bits(alternate as u8);
|
||||||
w.fun_ie().bit(open_drain);
|
if let Some(input_enable) = input_enable {
|
||||||
|
w.fun_ie().bit(input_enable);
|
||||||
|
}
|
||||||
w.fun_drv().bits(DriveStrength::I20mA as u8);
|
w.fun_drv().bits(DriveStrength::I20mA as u8);
|
||||||
w.slp_sel().clear_bit()
|
w.slp_sel().clear_bit()
|
||||||
});
|
});
|
||||||
@ -431,13 +442,13 @@ pub trait OutputPin: Pin + Into<AnyPin> + 'static {
|
|||||||
/// Configure open-drain mode
|
/// Configure open-drain mode
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn set_to_open_drain_output(&mut self, _: private::Internal) {
|
fn set_to_open_drain_output(&mut self, _: private::Internal) {
|
||||||
self.init_output(GPIO_FUNCTION, true, private::Internal);
|
self.init_output(GPIO_FUNCTION, true, Some(true), private::Internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure output mode
|
/// Configure output mode
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn set_to_push_pull_output(&mut self, _: private::Internal) {
|
fn set_to_push_pull_output(&mut self, _: private::Internal) {
|
||||||
self.init_output(GPIO_FUNCTION, false, private::Internal);
|
self.init_output(GPIO_FUNCTION, false, None, private::Internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the pin's level to high or low
|
/// Set the pin's level to high or low
|
||||||
@ -461,12 +472,6 @@ pub trait OutputPin: Pin + Into<AnyPin> + 'static {
|
|||||||
.modify(|_, w| w.pad_driver().bit(on));
|
.modify(|_, w| w.pad_driver().bit(on));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable/disable output in sleep mode
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
|
|
||||||
get_io_mux_reg(self.number()).modify(|_, w| w.mcu_oe().bit(on));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configure internal pull-up resistor in sleep mode
|
/// Configure internal pull-up resistor in sleep mode
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
|
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
|
||||||
@ -1115,9 +1120,9 @@ pub struct Output<'d, P = AnyPin> {
|
|||||||
|
|
||||||
impl<P> private::Sealed for Output<'_, P> {}
|
impl<P> private::Sealed for Output<'_, P> {}
|
||||||
|
|
||||||
impl<P> Peripheral for Output<'_, P> {
|
impl<'d, P> Peripheral for Output<'d, P> {
|
||||||
type P = P;
|
type P = Flex<'d, P>;
|
||||||
unsafe fn clone_unchecked(&self) -> P {
|
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||||
self.pin.clone_unchecked()
|
self.pin.clone_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1229,9 +1234,9 @@ pub struct Input<'d, P = AnyPin> {
|
|||||||
|
|
||||||
impl<P> private::Sealed for Input<'_, P> {}
|
impl<P> private::Sealed for Input<'_, P> {}
|
||||||
|
|
||||||
impl<P> Peripheral for Input<'_, P> {
|
impl<'d, P> Peripheral for Input<'d, P> {
|
||||||
type P = P;
|
type P = Flex<'d, P>;
|
||||||
unsafe fn clone_unchecked(&self) -> P {
|
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||||
self.pin.clone_unchecked()
|
self.pin.clone_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1350,9 +1355,9 @@ pub struct OutputOpenDrain<'d, P = AnyPin> {
|
|||||||
|
|
||||||
impl<P> private::Sealed for OutputOpenDrain<'_, P> {}
|
impl<P> private::Sealed for OutputOpenDrain<'_, P> {}
|
||||||
|
|
||||||
impl<P> Peripheral for OutputOpenDrain<'_, P> {
|
impl<'d, P> Peripheral for OutputOpenDrain<'d, P> {
|
||||||
type P = P;
|
type P = Flex<'d, P>;
|
||||||
unsafe fn clone_unchecked(&self) -> P {
|
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||||
self.pin.clone_unchecked()
|
self.pin.clone_unchecked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1498,10 +1503,12 @@ pub struct Flex<'d, P = AnyPin> {
|
|||||||
|
|
||||||
impl<P> private::Sealed for Flex<'_, P> {}
|
impl<P> private::Sealed for Flex<'_, P> {}
|
||||||
|
|
||||||
impl<P> Peripheral for Flex<'_, P> {
|
impl<'d, P> Peripheral for Flex<'d, P> {
|
||||||
type P = P;
|
type P = Self;
|
||||||
unsafe fn clone_unchecked(&self) -> P {
|
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||||
core::ptr::read(&*self.pin as *const _)
|
Self {
|
||||||
|
pin: PeripheralRef::new(core::ptr::read(&*self.pin as *const P)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1709,6 +1716,42 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unfortunate implementation details responsible for:
|
||||||
|
// - making pin drivers work with the peripheral signal system
|
||||||
|
// - making the pin drivers work with the sleep API
|
||||||
|
impl<P: Pin> Pin for Flex<'_, P> {
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.pin {
|
||||||
|
fn number(&self) -> u8;
|
||||||
|
fn degrade_pin(&self, _internal: private::Internal) -> AnyPin;
|
||||||
|
fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, OutputSignal)];
|
||||||
|
fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, InputSignal)];
|
||||||
|
fn gpio_bank(&self, _internal: private::Internal) -> GpioRegisterAccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<P: RtcPin> RtcPin for Flex<'_, P> {
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.pin {
|
||||||
|
#[cfg(xtensa)]
|
||||||
|
fn rtc_number(&self) -> u8;
|
||||||
|
#[cfg(any(xtensa, esp32c6))]
|
||||||
|
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: RtcFunction);
|
||||||
|
fn rtcio_pad_hold(&mut self, enable: bool);
|
||||||
|
#[cfg(any(esp32c3, esp32c2, esp32c6))]
|
||||||
|
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<P: RtcPinWithResistors> RtcPinWithResistors for Flex<'_, P> {
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.pin {
|
||||||
|
fn rtcio_pullup(&mut self, enable: bool);
|
||||||
|
fn rtcio_pulldown(&mut self, enable: bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod internal {
|
pub(crate) mod internal {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -1773,10 +1816,17 @@ pub(crate) mod internal {
|
|||||||
&mut self,
|
&mut self,
|
||||||
alternate: AlternateFunction,
|
alternate: AlternateFunction,
|
||||||
open_drain: bool,
|
open_drain: bool,
|
||||||
|
input_enable: Option<bool>,
|
||||||
_: private::Internal,
|
_: private::Internal,
|
||||||
) {
|
) {
|
||||||
handle_gpio_output!(&mut self.0, target, {
|
handle_gpio_output!(&mut self.0, target, {
|
||||||
OutputPin::init_output(target, alternate, open_drain, private::Internal)
|
OutputPin::init_output(
|
||||||
|
target,
|
||||||
|
alternate,
|
||||||
|
open_drain,
|
||||||
|
input_enable,
|
||||||
|
private::Internal,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1810,12 +1860,6 @@ pub(crate) mod 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) {
|
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) {
|
||||||
handle_gpio_output!(&mut self.0, target, {
|
handle_gpio_output!(&mut self.0, target, {
|
||||||
OutputPin::internal_pull_up_in_sleep_mode(target, on, private::Internal)
|
OutputPin::internal_pull_up_in_sleep_mode(target, on, private::Internal)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
// polluting the main module.
|
// polluting the main module.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::gpio::interconnect::connect_input_signal;
|
||||||
|
|
||||||
impl crate::peripheral::Peripheral for Level {
|
impl crate::peripheral::Peripheral for Level {
|
||||||
type P = Self;
|
type P = Self;
|
||||||
@ -29,45 +30,26 @@ impl Level {
|
|||||||
|
|
||||||
pub(crate) fn enable_input(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn enable_input(&mut self, _on: bool, _: private::Internal) {}
|
||||||
|
|
||||||
pub(crate) fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
|
||||||
|
|
||||||
pub(crate) fn is_input_high(&self, _: private::Internal) -> bool {
|
pub(crate) fn is_input_high(&self, _: private::Internal) -> bool {
|
||||||
*self == Level::High
|
*self == Level::High
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub(crate) fn connect_input_to_peripheral(
|
pub(crate) fn connect_input_to_peripheral(&mut self, signal: InputSignal) {
|
||||||
&mut self,
|
|
||||||
signal: InputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
let value = match self {
|
let value = match self {
|
||||||
Level::High => ONE_INPUT,
|
Level::High => ONE_INPUT,
|
||||||
Level::Low => ZERO_INPUT,
|
Level::Low => ZERO_INPUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { GPIO::steal() }
|
connect_input_signal(signal, value, false, true);
|
||||||
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
|
|
||||||
.modify(|_, w| unsafe {
|
|
||||||
w.sel().set_bit();
|
|
||||||
w.in_inv_sel().bit(false);
|
|
||||||
w.in_sel().bits(value)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn disconnect_input_from_peripheral(
|
|
||||||
&mut self,
|
|
||||||
_signal: InputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
pub(crate) fn set_to_open_drain_output(&mut self, _: private::Internal) {}
|
pub(crate) fn set_to_open_drain_output(&mut self, _: private::Internal) {}
|
||||||
pub(crate) fn set_to_push_pull_output(&mut self, _: private::Internal) {}
|
pub(crate) fn set_to_push_pull_output(&mut self, _: private::Internal) {}
|
||||||
pub(crate) fn enable_output(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn enable_output(&mut self, _on: bool, _: private::Internal) {}
|
||||||
pub(crate) fn set_output_high(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn set_output_high(&mut self, _on: bool, _: private::Internal) {}
|
||||||
pub(crate) fn set_drive_strength(&mut self, _strength: DriveStrength, _: private::Internal) {}
|
pub(crate) fn set_drive_strength(&mut self, _strength: DriveStrength, _: private::Internal) {}
|
||||||
pub(crate) fn enable_open_drain(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn enable_open_drain(&mut self, _on: bool, _: private::Internal) {}
|
||||||
pub(crate) fn enable_output_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
|
||||||
pub(crate) fn internal_pull_up_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn internal_pull_up_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
||||||
pub(crate) fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
pub(crate) fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
|
||||||
|
|
||||||
@ -82,19 +64,9 @@ impl Level {
|
|||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn connect_peripheral_to_output(
|
pub(crate) fn connect_peripheral_to_output(&mut self, _signal: OutputSignal) {}
|
||||||
&mut self,
|
|
||||||
_signal: OutputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn disconnect_from_peripheral_output(
|
pub(crate) fn disconnect_from_peripheral_output(&mut self, _signal: OutputSignal) {}
|
||||||
&mut self,
|
|
||||||
_signal: OutputSignal,
|
|
||||||
_: private::Internal,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Placeholder pin, used when no pin is required when using a peripheral.
|
/// Placeholder pin, used when no pin is required when using a peripheral.
|
||||||
|
|||||||
@ -336,15 +336,15 @@ where
|
|||||||
scl.enable_input(true, crate::private::Internal);
|
scl.enable_input(true, crate::private::Internal);
|
||||||
scl.pull_direction(Pull::Up, crate::private::Internal);
|
scl.pull_direction(Pull::Up, crate::private::Internal);
|
||||||
|
|
||||||
scl.connect_input_to_peripheral(i2c.i2c.scl_input_signal(), crate::private::Internal);
|
i2c.i2c.scl_input_signal().connect_to(&mut scl);
|
||||||
scl.connect_peripheral_to_output(i2c.i2c.scl_output_signal(), crate::private::Internal);
|
i2c.i2c.scl_output_signal().connect_to(&mut scl);
|
||||||
|
|
||||||
sda.set_to_open_drain_output(crate::private::Internal);
|
sda.set_to_open_drain_output(crate::private::Internal);
|
||||||
sda.enable_input(true, crate::private::Internal);
|
sda.enable_input(true, crate::private::Internal);
|
||||||
sda.pull_direction(Pull::Up, crate::private::Internal);
|
sda.pull_direction(Pull::Up, crate::private::Internal);
|
||||||
|
|
||||||
sda.connect_input_to_peripheral(i2c.i2c.sda_input_signal(), crate::private::Internal);
|
i2c.i2c.sda_input_signal().connect_to(&mut sda);
|
||||||
sda.connect_peripheral_to_output(i2c.i2c.sda_output_signal(), crate::private::Internal);
|
i2c.i2c.sda_output_signal().connect_to(&mut sda);
|
||||||
|
|
||||||
i2c.i2c.setup(frequency, None);
|
i2c.i2c.setup(frequency, None);
|
||||||
i2c
|
i2c
|
||||||
|
|||||||
@ -469,7 +469,7 @@ where
|
|||||||
pub fn with_mclk<P: PeripheralOutput>(self, pin: impl Peripheral<P = P> + 'd) -> Self {
|
pub fn with_mclk<P: PeripheralOutput>(self, pin: impl Peripheral<P = P> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(crate::private::Internal);
|
pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s_tx.i2s.mclk_signal(), crate::private::Internal);
|
self.i2s_tx.i2s.mclk_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -826,7 +826,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s.bclk_signal(), private::Internal);
|
self.i2s.bclk_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -837,7 +837,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s.ws_signal(), private::Internal);
|
self.i2s.ws_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -848,7 +848,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s.dout_signal(), private::Internal);
|
self.i2s.dout_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -885,7 +885,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s.bclk_rx_signal(), private::Internal);
|
self.i2s.bclk_rx_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -896,7 +896,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(private::Internal);
|
||||||
pin.connect_peripheral_to_output(self.i2s.ws_rx_signal(), private::Internal);
|
self.i2s.ws_rx_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -907,7 +907,7 @@ mod private {
|
|||||||
{
|
{
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.init_input(crate::gpio::Pull::None, private::Internal);
|
pin.init_input(crate::gpio::Pull::None, private::Internal);
|
||||||
pin.connect_input_to_peripheral(self.i2s.din_signal(), private::Internal);
|
self.i2s.din_signal().connect_to(pin);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::{i2s0::RegisterBlock, I2S0, I2S1},
|
peripherals::{i2s0::RegisterBlock, I2S0, I2S1},
|
||||||
private,
|
private::Internal,
|
||||||
system::PeripheralClockControl,
|
system::PeripheralClockControl,
|
||||||
Async,
|
Async,
|
||||||
Mode,
|
Mode,
|
||||||
@ -123,8 +123,8 @@ impl<'d> TxPins<'d> for TxSixteenBits<'d> {
|
|||||||
crate::into_ref!(instance);
|
crate::into_ref!(instance);
|
||||||
let bits = self.bus_width();
|
let bits = self.bus_width();
|
||||||
for (i, pin) in self.pins.iter_mut().enumerate() {
|
for (i, pin) in self.pins.iter_mut().enumerate() {
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(Internal);
|
||||||
pin.connect_peripheral_to_output(instance.data_out_signal(i, bits), private::Internal);
|
instance.data_out_signal(i, bits).connect_to(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,8 +165,8 @@ impl<'d> TxPins<'d> for TxEightBits<'d> {
|
|||||||
crate::into_ref!(instance);
|
crate::into_ref!(instance);
|
||||||
let bits = self.bus_width();
|
let bits = self.bus_width();
|
||||||
for (i, pin) in self.pins.iter_mut().enumerate() {
|
for (i, pin) in self.pins.iter_mut().enumerate() {
|
||||||
pin.set_to_push_pull_output(private::Internal);
|
pin.set_to_push_pull_output(Internal);
|
||||||
pin.connect_peripheral_to_output(instance.data_out_signal(i, bits), private::Internal);
|
instance.data_out_signal(i, bits).connect_to(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,8 +228,8 @@ where
|
|||||||
// configure the I2S peripheral for parallel mode
|
// configure the I2S peripheral for parallel mode
|
||||||
i2s.setup(frequency, pins.bus_width());
|
i2s.setup(frequency, pins.bus_width());
|
||||||
// setup the clock pin
|
// setup the clock pin
|
||||||
clock_pin.set_to_push_pull_output(private::Internal);
|
clock_pin.set_to_push_pull_output(Internal);
|
||||||
clock_pin.connect_peripheral_to_output(i2s.ws_signal(), private::Internal);
|
i2s.ws_signal().connect_to(clock_pin);
|
||||||
|
|
||||||
pins.configure(i2s.reborrow());
|
pins.configure(i2s.reborrow());
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
@ -243,8 +243,10 @@ impl<'d> Camera<'d> {
|
|||||||
mclk: impl Peripheral<P = MCLK> + 'd,
|
mclk: impl Peripheral<P = MCLK> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
crate::into_mapped_ref!(mclk);
|
crate::into_mapped_ref!(mclk);
|
||||||
|
|
||||||
mclk.set_to_push_pull_output(crate::private::Internal);
|
mclk.set_to_push_pull_output(crate::private::Internal);
|
||||||
mclk.connect_peripheral_to_output(OutputSignal::CAM_CLK, crate::private::Internal);
|
OutputSignal::CAM_CLK.connect_to(mclk);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +258,7 @@ impl<'d> Camera<'d> {
|
|||||||
crate::into_mapped_ref!(pclk);
|
crate::into_mapped_ref!(pclk);
|
||||||
|
|
||||||
pclk.init_input(Pull::None, crate::private::Internal);
|
pclk.init_input(Pull::None, crate::private::Internal);
|
||||||
pclk.connect_input_to_peripheral(InputSignal::CAM_PCLK, crate::private::Internal);
|
InputSignal::CAM_PCLK.connect_to(pclk);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -271,9 +273,9 @@ impl<'d> Camera<'d> {
|
|||||||
crate::into_mapped_ref!(vsync, h_enable);
|
crate::into_mapped_ref!(vsync, h_enable);
|
||||||
|
|
||||||
vsync.init_input(Pull::None, crate::private::Internal);
|
vsync.init_input(Pull::None, crate::private::Internal);
|
||||||
vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal);
|
InputSignal::CAM_V_SYNC.connect_to(vsync);
|
||||||
h_enable.init_input(Pull::None, crate::private::Internal);
|
h_enable.init_input(Pull::None, crate::private::Internal);
|
||||||
h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal);
|
InputSignal::CAM_H_ENABLE.connect_to(h_enable);
|
||||||
|
|
||||||
self.lcd_cam
|
self.lcd_cam
|
||||||
.cam_ctrl1()
|
.cam_ctrl1()
|
||||||
@ -297,11 +299,11 @@ impl<'d> Camera<'d> {
|
|||||||
crate::into_mapped_ref!(vsync, hsync, h_enable);
|
crate::into_mapped_ref!(vsync, hsync, h_enable);
|
||||||
|
|
||||||
vsync.init_input(Pull::None, crate::private::Internal);
|
vsync.init_input(Pull::None, crate::private::Internal);
|
||||||
vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal);
|
InputSignal::CAM_V_SYNC.connect_to(vsync);
|
||||||
hsync.init_input(Pull::None, crate::private::Internal);
|
hsync.init_input(Pull::None, crate::private::Internal);
|
||||||
hsync.connect_input_to_peripheral(InputSignal::CAM_H_SYNC, crate::private::Internal);
|
InputSignal::CAM_H_SYNC.connect_to(hsync);
|
||||||
h_enable.init_input(Pull::None, crate::private::Internal);
|
h_enable.init_input(Pull::None, crate::private::Internal);
|
||||||
h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal);
|
InputSignal::CAM_H_ENABLE.connect_to(h_enable);
|
||||||
|
|
||||||
self.lcd_cam
|
self.lcd_cam
|
||||||
.cam_ctrl1()
|
.cam_ctrl1()
|
||||||
@ -514,9 +516,9 @@ impl RxEightBits {
|
|||||||
(pin_7, InputSignal::CAM_DATA_7),
|
(pin_7, InputSignal::CAM_DATA_7),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (mut pin, signal) in pairs.into_iter() {
|
for (pin, signal) in pairs.into_iter() {
|
||||||
pin.init_input(Pull::None, crate::private::Internal);
|
pin.init_input(Pull::None, crate::private::Internal);
|
||||||
pin.connect_input_to_peripheral(signal, crate::private::Internal);
|
signal.connect_to(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { _pins: () }
|
Self { _pins: () }
|
||||||
@ -591,9 +593,9 @@ impl RxSixteenBits {
|
|||||||
(pin_15, InputSignal::CAM_DATA_15),
|
(pin_15, InputSignal::CAM_DATA_15),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (mut pin, signal) in pairs.into_iter() {
|
for (pin, signal) in pairs.into_iter() {
|
||||||
pin.init_input(Pull::None, crate::private::Internal);
|
pin.init_input(Pull::None, crate::private::Internal);
|
||||||
pin.connect_input_to_peripheral(signal, crate::private::Internal);
|
signal.connect_to(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { _pins: () }
|
Self { _pins: () }
|
||||||
|
|||||||
@ -239,7 +239,7 @@ impl<'d, DM: Mode> I8080<'d, DM> {
|
|||||||
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(cs);
|
crate::into_mapped_ref!(cs);
|
||||||
cs.set_to_push_pull_output(crate::private::Internal);
|
cs.set_to_push_pull_output(crate::private::Internal);
|
||||||
cs.connect_peripheral_to_output(OutputSignal::LCD_CS, crate::private::Internal);
|
OutputSignal::LCD_CS.connect_to(cs);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -253,10 +253,10 @@ impl<'d, DM: Mode> I8080<'d, DM> {
|
|||||||
crate::into_mapped_ref!(dc, wrx);
|
crate::into_mapped_ref!(dc, wrx);
|
||||||
|
|
||||||
dc.set_to_push_pull_output(crate::private::Internal);
|
dc.set_to_push_pull_output(crate::private::Internal);
|
||||||
dc.connect_peripheral_to_output(OutputSignal::LCD_DC, crate::private::Internal);
|
OutputSignal::LCD_DC.connect_to(dc);
|
||||||
|
|
||||||
wrx.set_to_push_pull_output(crate::private::Internal);
|
wrx.set_to_push_pull_output(crate::private::Internal);
|
||||||
wrx.connect_peripheral_to_output(OutputSignal::LCD_PCLK, crate::private::Internal);
|
OutputSignal::LCD_PCLK.connect_to(wrx);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -628,9 +628,9 @@ impl<'d> TxPins for TxEightBits<'d> {
|
|||||||
OutputSignal::LCD_DATA_7,
|
OutputSignal::LCD_DATA_7,
|
||||||
];
|
];
|
||||||
|
|
||||||
for (pin, signal) in self.pins.iter_mut().zip(SIGNALS.iter()) {
|
for (pin, signal) in self.pins.iter_mut().zip(SIGNALS.into_iter()) {
|
||||||
pin.set_to_push_pull_output(crate::private::Internal);
|
pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
pin.connect_peripheral_to_output(*signal, crate::private::Internal);
|
signal.connect_to(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -697,9 +697,9 @@ impl<'d> TxPins for TxSixteenBits<'d> {
|
|||||||
OutputSignal::LCD_DATA_15,
|
OutputSignal::LCD_DATA_15,
|
||||||
];
|
];
|
||||||
|
|
||||||
for (pin, signal) in self.pins.iter_mut().zip(SIGNALS.iter()) {
|
for (pin, signal) in self.pins.iter_mut().zip(SIGNALS.into_iter()) {
|
||||||
pin.set_to_push_pull_output(crate::private::Internal);
|
pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
pin.connect_peripheral_to_output(*signal, crate::private::Internal);
|
signal.connect_to(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -610,8 +610,7 @@ where
|
|||||||
Number::Channel7 => OutputSignal::LEDC_LS_SIG7,
|
Number::Channel7 => OutputSignal::LEDC_LS_SIG7,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.output_pin
|
signal.connect_to(&mut self.output_pin);
|
||||||
.connect_peripheral_to_output(signal, crate::private::Internal);
|
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Timer);
|
return Err(Error::Timer);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,23 @@ macro_rules! before_snippet {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_markdown_link {
|
||||||
|
() => {
|
||||||
|
concat!("[Technical Reference Manual](", $crate::trm_link!(), ")")
|
||||||
|
};
|
||||||
|
($anchor:literal) => {
|
||||||
|
concat!(
|
||||||
|
"[Technical Reference Manual](",
|
||||||
|
$crate::trm_link!(),
|
||||||
|
"#",
|
||||||
|
$anchor,
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Shorthand to define enums with From implementations.
|
/// Shorthand to define enums with From implementations.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|||||||
@ -298,9 +298,7 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP,
|
|||||||
pin.set_actions(config.actions);
|
pin.set_actions(config.actions);
|
||||||
pin.set_update_method(config.update_method);
|
pin.set_update_method(config.update_method);
|
||||||
|
|
||||||
let output_signal = PWM::output_signal::<OP, IS_A>();
|
PWM::output_signal::<OP, IS_A>().connect_to(&mut pin.pin);
|
||||||
pin.pin
|
|
||||||
.connect_peripheral_to_output(output_signal, private::Internal);
|
|
||||||
pin.pin.enable_output(true, private::Internal);
|
pin.pin.enable_output(true, private::Internal);
|
||||||
|
|
||||||
pin
|
pin
|
||||||
|
|||||||
@ -43,7 +43,6 @@ use crate::{
|
|||||||
gpio::InputSignal,
|
gpio::InputSignal,
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals,
|
peripherals,
|
||||||
private::Internal,
|
|
||||||
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
|
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,10 +98,10 @@ impl<'d> Usb<'d> {
|
|||||||
|
|
||||||
use crate::gpio::Level;
|
use crate::gpio::Level;
|
||||||
|
|
||||||
Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_IDDIG, Internal); // connected connector is mini-B side
|
InputSignal::USB_OTG_IDDIG.connect_to(Level::High); // connected connector is mini-B side
|
||||||
Level::High.connect_input_to_peripheral(InputSignal::USB_SRP_BVALID, Internal); // HIGH to force USB device mode
|
InputSignal::USB_SRP_BVALID.connect_to(Level::High); // HIGH to force USB device mode
|
||||||
Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_VBUSVALID, Internal); // receiving a valid Vbus from device
|
InputSignal::USB_OTG_VBUSVALID.connect_to(Level::High); // receiving a valid Vbus from device
|
||||||
Level::Low.connect_input_to_peripheral(InputSignal::USB_OTG_AVALID, Internal);
|
InputSignal::USB_OTG_AVALID.connect_to(Level::Low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -292,10 +292,7 @@ impl<'d> ClkOutPin<'d> {
|
|||||||
impl TxClkPin for ClkOutPin<'_> {
|
impl TxClkPin for ClkOutPin<'_> {
|
||||||
fn configure(&mut self) {
|
fn configure(&mut self) {
|
||||||
self.pin.set_to_push_pull_output(crate::private::Internal);
|
self.pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
self.pin.connect_peripheral_to_output(
|
crate::gpio::OutputSignal::PARL_TX_CLK.connect_to(&mut self.pin);
|
||||||
crate::gpio::OutputSignal::PARL_TX_CLK,
|
|
||||||
crate::private::Internal,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,10 +315,7 @@ impl TxClkPin for ClkInPin<'_> {
|
|||||||
|
|
||||||
self.pin
|
self.pin
|
||||||
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
||||||
self.pin.connect_input_to_peripheral(
|
crate::gpio::InputSignal::PARL_TX_CLK.connect_to(&mut self.pin);
|
||||||
crate::gpio::InputSignal::PARL_TX_CLK,
|
|
||||||
crate::private::Internal,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,10 +342,7 @@ impl RxClkPin for RxClkInPin<'_> {
|
|||||||
|
|
||||||
self.pin
|
self.pin
|
||||||
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
||||||
self.pin.connect_input_to_peripheral(
|
crate::gpio::InputSignal::PARL_RX_CLK.connect_to(&mut self.pin);
|
||||||
crate::gpio::InputSignal::PARL_RX_CLK,
|
|
||||||
crate::private::Internal,
|
|
||||||
);
|
|
||||||
|
|
||||||
Instance::set_rx_clk_edge_sel(self.sample_edge);
|
Instance::set_rx_clk_edge_sel(self.sample_edge);
|
||||||
}
|
}
|
||||||
@ -390,10 +381,7 @@ where
|
|||||||
self.tx_pins.configure()?;
|
self.tx_pins.configure()?;
|
||||||
self.valid_pin
|
self.valid_pin
|
||||||
.set_to_push_pull_output(crate::private::Internal);
|
.set_to_push_pull_output(crate::private::Internal);
|
||||||
self.valid_pin.connect_peripheral_to_output(
|
Instance::tx_valid_pin_signal().connect_to(&mut self.valid_pin);
|
||||||
Instance::tx_valid_pin_signal(),
|
|
||||||
crate::private::Internal,
|
|
||||||
);
|
|
||||||
Instance::set_tx_hw_valid_en(true);
|
Instance::set_tx_hw_valid_en(true);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -464,7 +452,7 @@ macro_rules! tx_pins {
|
|||||||
fn configure(&mut self) -> Result<(), Error>{
|
fn configure(&mut self) -> Result<(), Error>{
|
||||||
$(
|
$(
|
||||||
self.[< pin_ $pin:lower >].set_to_push_pull_output(crate::private::Internal);
|
self.[< pin_ $pin:lower >].set_to_push_pull_output(crate::private::Internal);
|
||||||
self.[< pin_ $pin:lower >].connect_peripheral_to_output(crate::gpio::OutputSignal::$signal, crate::private::Internal);
|
crate::gpio::OutputSignal::$signal.connect_to(&mut self.[< pin_ $pin:lower >]);
|
||||||
)+
|
)+
|
||||||
|
|
||||||
private::Instance::set_tx_bit_width( private::WidSel::[< Bits $width >]);
|
private::Instance::set_tx_bit_width( private::WidSel::[< Bits $width >]);
|
||||||
@ -584,8 +572,7 @@ where
|
|||||||
self.rx_pins.configure()?;
|
self.rx_pins.configure()?;
|
||||||
self.valid_pin
|
self.valid_pin
|
||||||
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
||||||
self.valid_pin
|
Instance::rx_valid_pin_signal().connect_to(&mut self.valid_pin);
|
||||||
.connect_input_to_peripheral(Instance::rx_valid_pin_signal(), crate::private::Internal);
|
|
||||||
Instance::set_rx_sw_en(false);
|
Instance::set_rx_sw_en(false);
|
||||||
if let Some(sel) = self.enable_mode.pulse_submode_sel() {
|
if let Some(sel) = self.enable_mode.pulse_submode_sel() {
|
||||||
Instance::set_rx_pulse_submode_sel(sel);
|
Instance::set_rx_pulse_submode_sel(sel);
|
||||||
@ -684,7 +671,7 @@ macro_rules! rx_pins {
|
|||||||
fn configure(&mut self) -> Result<(), Error> {
|
fn configure(&mut self) -> Result<(), Error> {
|
||||||
$(
|
$(
|
||||||
self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None, crate::private::Internal);
|
self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None, crate::private::Internal);
|
||||||
self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, crate::private::Internal);
|
crate::gpio::InputSignal::$signal.connect_to(&mut self.[< pin_ $pin:lower >]);
|
||||||
)+
|
)+
|
||||||
|
|
||||||
private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]);
|
private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]);
|
||||||
|
|||||||
@ -118,7 +118,7 @@ impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
|
|||||||
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
|
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
|
||||||
crate::into_mapped_ref!(source);
|
crate::into_mapped_ref!(source);
|
||||||
source.enable_input(true, crate::private::Internal);
|
source.enable_input(true, crate::private::Internal);
|
||||||
source.connect_input_to_peripheral(signal, crate::private::Internal);
|
signal.connect_to(source);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
|
|||||||
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
|
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
|
||||||
crate::into_mapped_ref!(source);
|
crate::into_mapped_ref!(source);
|
||||||
source.enable_input(true, crate::private::Internal);
|
source.enable_input(true, crate::private::Internal);
|
||||||
source.connect_input_to_peripheral(signal, crate::private::Internal);
|
signal.connect_to(source);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@ -312,8 +312,8 @@ fn configure_rx_channel<'d, P: PeripheralInput, T: RxChannelInternal<M>, M: crat
|
|||||||
}
|
}
|
||||||
|
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.init_input(crate::gpio::Pull::None, crate::Internal);
|
pin.init_input(crate::gpio::Pull::None, crate::private::Internal);
|
||||||
pin.connect_input_to_peripheral(T::input_signal(), crate::Internal);
|
T::input_signal().connect_to(pin);
|
||||||
|
|
||||||
T::set_divider(config.clk_divider);
|
T::set_divider(config.clk_divider);
|
||||||
T::set_carrier(
|
T::set_carrier(
|
||||||
@ -333,8 +333,8 @@ fn configure_tx_channel<'d, P: PeripheralOutput, T: TxChannelInternal<M>, M: cra
|
|||||||
config: TxChannelConfig,
|
config: TxChannelConfig,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
crate::into_mapped_ref!(pin);
|
crate::into_mapped_ref!(pin);
|
||||||
pin.set_to_push_pull_output(crate::Internal);
|
pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
pin.connect_peripheral_to_output(T::output_signal(), crate::Internal);
|
T::output_signal().connect_to(pin);
|
||||||
|
|
||||||
T::set_divider(config.clk_divider);
|
T::set_divider(config.clk_divider);
|
||||||
T::set_carrier(
|
T::set_carrier(
|
||||||
|
|||||||
@ -53,6 +53,7 @@ pub const NUM_PINS: usize = 40;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u16;
|
||||||
pub(crate) type OutputSignalType = u16;
|
pub(crate) type OutputSignalType = u16;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 548;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 548;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u16 = 539;
|
pub(crate) const INPUT_SIGNAL_MAX: u16 = 539;
|
||||||
@ -119,7 +120,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
SPICLK = 0,
|
SPICLK = 0,
|
||||||
@ -310,7 +312,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral output signals for the GPIO mux
|
/// Peripheral output signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
SPICLK = 0,
|
SPICLK = 0,
|
||||||
|
|||||||
@ -26,6 +26,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
pub(crate) mod constants {
|
pub(crate) mod constants {
|
||||||
|
|||||||
@ -45,6 +45,7 @@ pub const NUM_PINS: usize = 21;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u8;
|
||||||
pub(crate) type OutputSignalType = u8;
|
pub(crate) type OutputSignalType = u8;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u8 = 100;
|
pub(crate) const INPUT_SIGNAL_MAX: u8 = 100;
|
||||||
@ -64,7 +65,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
@ -104,7 +106,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral output signals for the GPIO mux
|
/// Peripheral output signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
|
|||||||
@ -19,6 +19,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@ -46,6 +46,7 @@ pub const NUM_PINS: usize = 22;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u8;
|
||||||
pub(crate) type OutputSignalType = u8;
|
pub(crate) type OutputSignalType = u8;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u8 = 100;
|
pub(crate) const INPUT_SIGNAL_MAX: u8 = 100;
|
||||||
@ -65,7 +66,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
@ -114,7 +116,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral output signals for the GPIO mux
|
/// Peripheral output signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
|
|||||||
@ -23,6 +23,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@ -46,6 +46,7 @@ pub const NUM_PINS: usize = 31;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u8;
|
||||||
pub(crate) type OutputSignalType = u8;
|
pub(crate) type OutputSignalType = u8;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u8 = 124;
|
pub(crate) const INPUT_SIGNAL_MAX: u8 = 124;
|
||||||
@ -65,7 +66,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
EXT_ADC_START = 0,
|
EXT_ADC_START = 0,
|
||||||
@ -169,7 +171,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
LEDC_LS_SIG0 = 0,
|
LEDC_LS_SIG0 = 0,
|
||||||
|
|||||||
@ -25,6 +25,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@ -47,6 +47,7 @@ pub const NUM_PINS: usize = 28;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u8;
|
||||||
pub(crate) type OutputSignalType = u8;
|
pub(crate) type OutputSignalType = u8;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u8 = 128;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u8 = 124;
|
pub(crate) const INPUT_SIGNAL_MAX: u8 = 124;
|
||||||
@ -66,7 +67,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
EXT_ADC_START = 0,
|
EXT_ADC_START = 0,
|
||||||
@ -151,7 +153,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
LEDC_LS_SIG0 = 0,
|
LEDC_LS_SIG0 = 0,
|
||||||
|
|||||||
@ -24,6 +24,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@ -59,6 +59,7 @@ pub const NUM_PINS: usize = 47;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u16;
|
||||||
pub(crate) type OutputSignalType = u16;
|
pub(crate) type OutputSignalType = u16;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 256;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 256;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u16 = 204;
|
pub(crate) const INPUT_SIGNAL_MAX: u16 = 204;
|
||||||
@ -126,7 +127,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
@ -212,7 +214,8 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral output signals for the GPIO mux
|
/// Peripheral output signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
|
|||||||
@ -31,6 +31,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
pub(crate) mod constants {
|
pub(crate) mod constants {
|
||||||
|
|||||||
@ -46,6 +46,7 @@ pub const NUM_PINS: usize = 49;
|
|||||||
|
|
||||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub(crate) type InputSignalType = u16;
|
||||||
pub(crate) type OutputSignalType = u16;
|
pub(crate) type OutputSignalType = u16;
|
||||||
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 256;
|
pub(crate) const OUTPUT_SIGNAL_MAX: u16 = 256;
|
||||||
pub(crate) const INPUT_SIGNAL_MAX: u16 = 189;
|
pub(crate) const INPUT_SIGNAL_MAX: u16 = 189;
|
||||||
@ -65,7 +66,8 @@ pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
|
|||||||
|
|
||||||
/// Peripheral input signals for the GPIO mux
|
/// Peripheral input signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub enum InputSignal {
|
pub enum InputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
@ -203,8 +205,10 @@ pub enum InputSignal {
|
|||||||
|
|
||||||
/// Peripheral output signals for the GPIO mux
|
/// Peripheral output signals for the GPIO mux
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
#[doc(hidden)]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[doc(hidden)] // TODO connection operations are now public on these, we might want to publish
|
||||||
|
// them
|
||||||
pub enum OutputSignal {
|
pub enum OutputSignal {
|
||||||
SPIQ = 0,
|
SPIQ = 0,
|
||||||
SPID = 1,
|
SPID = 1,
|
||||||
|
|||||||
@ -32,6 +32,12 @@ macro_rules! chip {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A link to the Technical Reference Manual (TRM) for the chip.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! trm_link {
|
||||||
|
() => { "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" };
|
||||||
|
}
|
||||||
|
|
||||||
pub use chip;
|
pub use chip;
|
||||||
|
|
||||||
pub(crate) mod constants {
|
pub(crate) mod constants {
|
||||||
|
|||||||
@ -90,12 +90,7 @@ use crate::{
|
|||||||
Rx,
|
Rx,
|
||||||
Tx,
|
Tx,
|
||||||
},
|
},
|
||||||
gpio::{
|
gpio::{interconnect::PeripheralOutput, InputSignal, NoPin, OutputSignal},
|
||||||
interconnect::{OutputConnection, PeripheralOutput},
|
|
||||||
InputSignal,
|
|
||||||
NoPin,
|
|
||||||
OutputSignal,
|
|
||||||
},
|
|
||||||
interrupt::InterruptHandler,
|
interrupt::InterruptHandler,
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::spi2::RegisterBlock,
|
peripherals::spi2::RegisterBlock,
|
||||||
@ -608,20 +603,10 @@ where
|
|||||||
|
|
||||||
let is_qspi = this.driver().sio2_input.is_some();
|
let is_qspi = this.driver().sio2_input.is_some();
|
||||||
if is_qspi {
|
if is_qspi {
|
||||||
let mut signal = OutputConnection::from(NoPin);
|
unwrap!(this.driver().sio2_input).connect_to(NoPin);
|
||||||
|
unwrap!(this.driver().sio2_output).connect_to(NoPin);
|
||||||
signal
|
unwrap!(this.driver().sio3_input).connect_to(NoPin);
|
||||||
.connect_input_to_peripheral(unwrap!(this.driver().sio2_input), private::Internal);
|
unwrap!(this.driver().sio3_output).connect_to(NoPin);
|
||||||
signal.connect_peripheral_to_output(
|
|
||||||
unwrap!(this.driver().sio2_output),
|
|
||||||
private::Internal,
|
|
||||||
);
|
|
||||||
signal
|
|
||||||
.connect_input_to_peripheral(unwrap!(this.driver().sio3_input), private::Internal);
|
|
||||||
signal.connect_peripheral_to_output(
|
|
||||||
unwrap!(this.driver().sio3_output),
|
|
||||||
private::Internal,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this
|
this
|
||||||
@ -634,10 +619,10 @@ where
|
|||||||
pub fn with_mosi<MOSI: PeripheralOutput>(self, mosi: impl Peripheral<P = MOSI> + 'd) -> Self {
|
pub fn with_mosi<MOSI: PeripheralOutput>(self, mosi: impl Peripheral<P = MOSI> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(mosi);
|
crate::into_mapped_ref!(mosi);
|
||||||
mosi.enable_output(true, private::Internal);
|
mosi.enable_output(true, private::Internal);
|
||||||
mosi.connect_peripheral_to_output(self.driver().mosi, private::Internal);
|
|
||||||
|
|
||||||
mosi.enable_input(true, private::Internal);
|
mosi.enable_input(true, private::Internal);
|
||||||
mosi.connect_input_to_peripheral(self.driver().sio0_input, private::Internal);
|
|
||||||
|
self.driver().mosi.connect_to(&mut mosi);
|
||||||
|
self.driver().sio0_input.connect_to(&mut mosi);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -649,10 +634,10 @@ where
|
|||||||
pub fn with_miso<MISO: PeripheralOutput>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
|
pub fn with_miso<MISO: PeripheralOutput>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(miso);
|
crate::into_mapped_ref!(miso);
|
||||||
miso.enable_input(true, private::Internal);
|
miso.enable_input(true, private::Internal);
|
||||||
miso.connect_input_to_peripheral(self.driver().miso, private::Internal);
|
|
||||||
|
|
||||||
miso.enable_output(true, private::Internal);
|
miso.enable_output(true, private::Internal);
|
||||||
miso.connect_peripheral_to_output(self.driver().sio1_output, private::Internal);
|
|
||||||
|
self.driver().miso.connect_to(&mut miso);
|
||||||
|
self.driver().sio1_output.connect_to(&mut miso);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -664,7 +649,7 @@ where
|
|||||||
pub fn with_sck<SCK: PeripheralOutput>(self, sclk: impl Peripheral<P = SCK> + 'd) -> Self {
|
pub fn with_sck<SCK: PeripheralOutput>(self, sclk: impl Peripheral<P = SCK> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(sclk);
|
crate::into_mapped_ref!(sclk);
|
||||||
sclk.set_to_push_pull_output(private::Internal);
|
sclk.set_to_push_pull_output(private::Internal);
|
||||||
sclk.connect_peripheral_to_output(self.driver().sclk, private::Internal);
|
self.driver().sclk.connect_to(sclk);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -676,7 +661,7 @@ where
|
|||||||
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(cs);
|
crate::into_mapped_ref!(cs);
|
||||||
cs.set_to_push_pull_output(private::Internal);
|
cs.set_to_push_pull_output(private::Internal);
|
||||||
cs.connect_peripheral_to_output(self.driver().cs, private::Internal);
|
self.driver().cs.connect_to(cs);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -716,8 +701,8 @@ where
|
|||||||
sio2.enable_input(true, private::Internal);
|
sio2.enable_input(true, private::Internal);
|
||||||
sio2.enable_output(true, private::Internal);
|
sio2.enable_output(true, private::Internal);
|
||||||
|
|
||||||
sio2.connect_input_to_peripheral(unwrap!(self.driver().sio2_input), private::Internal);
|
unwrap!(self.driver().sio2_input).connect_to(&mut sio2);
|
||||||
sio2.connect_peripheral_to_output(unwrap!(self.driver().sio2_output), private::Internal);
|
unwrap!(self.driver().sio2_output).connect_to(&mut sio2);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -734,8 +719,8 @@ where
|
|||||||
sio3.enable_input(true, private::Internal);
|
sio3.enable_input(true, private::Internal);
|
||||||
sio3.enable_output(true, private::Internal);
|
sio3.enable_output(true, private::Internal);
|
||||||
|
|
||||||
sio3.connect_input_to_peripheral(unwrap!(self.driver().sio3_input), private::Internal);
|
unwrap!(self.driver().sio3_input).connect_to(&mut sio3);
|
||||||
sio3.connect_peripheral_to_output(unwrap!(self.driver().sio3_output), private::Internal);
|
unwrap!(self.driver().sio3_output).connect_to(&mut sio3);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,16 +144,16 @@ where
|
|||||||
|
|
||||||
// TODO: with_pins et. al.
|
// TODO: with_pins et. al.
|
||||||
sclk.enable_input(true, private::Internal);
|
sclk.enable_input(true, private::Internal);
|
||||||
sclk.connect_input_to_peripheral(this.spi.sclk_signal(), private::Internal);
|
this.spi.sclk_signal().connect_to(sclk);
|
||||||
|
|
||||||
mosi.enable_input(true, private::Internal);
|
mosi.enable_input(true, private::Internal);
|
||||||
mosi.connect_input_to_peripheral(this.spi.mosi_signal(), private::Internal);
|
this.spi.mosi_signal().connect_to(mosi);
|
||||||
|
|
||||||
miso.set_to_push_pull_output(private::Internal);
|
miso.set_to_push_pull_output(private::Internal);
|
||||||
miso.connect_peripheral_to_output(this.spi.miso_signal(), private::Internal);
|
this.spi.miso_signal().connect_to(miso);
|
||||||
|
|
||||||
cs.enable_input(true, private::Internal);
|
cs.enable_input(true, private::Internal);
|
||||||
cs.connect_input_to_peripheral(this.spi.cs_signal(), private::Internal);
|
this.spi.cs_signal().connect_to(cs);
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|||||||
@ -806,13 +806,13 @@ where
|
|||||||
tx_pin.set_to_push_pull_output(crate::private::Internal);
|
tx_pin.set_to_push_pull_output(crate::private::Internal);
|
||||||
Pull::None
|
Pull::None
|
||||||
};
|
};
|
||||||
tx_pin.connect_peripheral_to_output(this.twai.output_signal(), crate::private::Internal);
|
this.twai.output_signal().connect_to(tx_pin);
|
||||||
|
|
||||||
// Setting up RX pin later allows us to use a single pin in tests.
|
// Setting up RX pin later allows us to use a single pin in tests.
|
||||||
// `set_to_push_pull_output` disables input, here we re-enable it if rx_pin
|
// `set_to_push_pull_output` disables input, here we re-enable it if rx_pin
|
||||||
// uses the same GPIO.
|
// uses the same GPIO.
|
||||||
rx_pin.init_input(rx_pull, crate::private::Internal);
|
rx_pin.init_input(rx_pull, crate::private::Internal);
|
||||||
rx_pin.connect_input_to_peripheral(this.twai.input_signal(), crate::private::Internal);
|
this.twai.input_signal().connect_to(rx_pin);
|
||||||
|
|
||||||
// Freeze REC by changing to LOM mode
|
// Freeze REC by changing to LOM mode
|
||||||
this.set_mode(TwaiMode::ListenOnly);
|
this.set_mode(TwaiMode::ListenOnly);
|
||||||
|
|||||||
@ -460,7 +460,7 @@ where
|
|||||||
fn with_rx(self, rx: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
|
fn with_rx(self, rx: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(rx);
|
crate::into_mapped_ref!(rx);
|
||||||
rx.init_input(Pull::Up, Internal);
|
rx.init_input(Pull::Up, Internal);
|
||||||
rx.connect_input_to_peripheral(self.uart.info().rx_signal, Internal);
|
self.uart.info().rx_signal.connect_to(rx);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -470,7 +470,7 @@ where
|
|||||||
// Make sure we don't cause an unexpected low pulse on the pin.
|
// Make sure we don't cause an unexpected low pulse on the pin.
|
||||||
tx.set_output_high(true, Internal);
|
tx.set_output_high(true, Internal);
|
||||||
tx.set_to_push_pull_output(Internal);
|
tx.set_to_push_pull_output(Internal);
|
||||||
tx.connect_peripheral_to_output(self.uart.info().tx_signal, Internal);
|
self.uart.info().tx_signal.connect_to(tx);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -558,7 +558,7 @@ where
|
|||||||
pub fn with_rts(self, rts: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self {
|
pub fn with_rts(self, rts: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(rts);
|
crate::into_mapped_ref!(rts);
|
||||||
rts.set_to_push_pull_output(Internal);
|
rts.set_to_push_pull_output(Internal);
|
||||||
rts.connect_peripheral_to_output(self.uart.info().rts_signal, Internal);
|
self.uart.info().rts_signal.connect_to(rts);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -766,7 +766,7 @@ where
|
|||||||
pub fn with_cts(self, cts: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
|
pub fn with_cts(self, cts: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
|
||||||
crate::into_mapped_ref!(cts);
|
crate::into_mapped_ref!(cts);
|
||||||
cts.init_input(Pull::None, Internal);
|
cts.init_input(Pull::None, Internal);
|
||||||
cts.connect_input_to_peripheral(self.uart.info().cts_signal, Internal);
|
self.uart.info().cts_signal.connect_to(cts);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,10 +11,8 @@
|
|||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
dma::{Dma, DmaPriority},
|
dma::{Dma, DmaPriority},
|
||||||
dma_buffers,
|
dma_buffers,
|
||||||
gpio::{
|
gpio::{Input, Io, Level, Output, Pull},
|
||||||
interconnect::{InputSignal, OutputSignal},
|
peripheral::Peripheral,
|
||||||
Io,
|
|
||||||
},
|
|
||||||
spi::{slave::Spi, SpiMode},
|
spi::{slave::Spi, SpiMode},
|
||||||
Blocking,
|
Blocking,
|
||||||
};
|
};
|
||||||
@ -35,32 +33,19 @@ struct Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct BitbangSpi {
|
struct BitbangSpi {
|
||||||
sclk: OutputSignal,
|
sclk: Output<'static>,
|
||||||
mosi: OutputSignal,
|
mosi: Output<'static>,
|
||||||
miso: InputSignal,
|
miso: Input<'static>,
|
||||||
cs: OutputSignal,
|
cs: Output<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitbangSpi {
|
impl BitbangSpi {
|
||||||
fn new(
|
fn new(
|
||||||
mut sclk: OutputSignal,
|
sclk: Output<'static>,
|
||||||
mut mosi: OutputSignal,
|
mosi: Output<'static>,
|
||||||
mut miso: InputSignal,
|
miso: Input<'static>,
|
||||||
mut cs: OutputSignal,
|
cs: Output<'static>,
|
||||||
) -> Self {
|
) -> 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 {
|
Self {
|
||||||
sclk,
|
sclk,
|
||||||
mosi,
|
mosi,
|
||||||
@ -70,29 +55,22 @@ impl BitbangSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn assert_cs(&mut self) {
|
fn assert_cs(&mut self) {
|
||||||
self.sclk
|
self.sclk.set_level(Level::Low);
|
||||||
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
|
self.cs.set_level(Level::Low);
|
||||||
self.cs
|
|
||||||
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deassert_cs(&mut self) {
|
fn deassert_cs(&mut self) {
|
||||||
self.sclk
|
self.sclk.set_level(Level::Low);
|
||||||
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
|
self.cs.set_level(Level::High);
|
||||||
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.
|
// Mode 1, so sampled on the rising edge and set on the falling edge.
|
||||||
fn shift_bit(&mut self, bit: bool) -> bool {
|
fn shift_bit(&mut self, bit: bool) -> bool {
|
||||||
self.mosi
|
self.mosi.set_level(Level::from(bit));
|
||||||
.set_output_high(bit, unsafe { esp_hal::Internal::conjure() });
|
self.sclk.set_level(Level::High);
|
||||||
self.sclk
|
|
||||||
.set_output_high(true, unsafe { esp_hal::Internal::conjure() });
|
|
||||||
|
|
||||||
let miso = self.miso.get_level().into();
|
let miso = self.miso.get_level().into();
|
||||||
self.sclk
|
self.sclk.set_level(Level::Low);
|
||||||
.set_output_high(false, unsafe { esp_hal::Internal::conjure() });
|
|
||||||
|
|
||||||
miso
|
miso
|
||||||
}
|
}
|
||||||
@ -141,21 +119,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (cs, cs_pin) = cs_pin.split();
|
let mosi_gpio = Output::new(mosi_pin, Level::Low);
|
||||||
let (mosi, mosi_pin) = mosi_pin.split();
|
let cs_gpio = Output::new(cs_pin, Level::High);
|
||||||
let (miso, miso_pin) = miso_pin.split();
|
let sclk_gpio = Output::new(sclk_pin, Level::Low);
|
||||||
let (sclk_signal, sclk_pin) = sclk_pin.split();
|
let miso_gpio = Input::new(miso_pin, Pull::None);
|
||||||
|
|
||||||
|
let cs = cs_gpio.peripheral_input();
|
||||||
|
let sclk = sclk_gpio.peripheral_input();
|
||||||
|
let mosi = mosi_gpio.peripheral_input();
|
||||||
|
let miso = unsafe { miso_gpio.clone_unchecked() }.into_peripheral_output();
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
spi: Spi::new(
|
spi: Spi::new(peripherals.SPI2, sclk, mosi, miso, cs, SpiMode::Mode1),
|
||||||
peripherals.SPI2,
|
bitbang_spi: BitbangSpi::new(sclk_gpio, mosi_gpio, miso_gpio, cs_gpio),
|
||||||
sclk_signal,
|
|
||||||
mosi,
|
|
||||||
miso_pin,
|
|
||||||
cs,
|
|
||||||
SpiMode::Mode1,
|
|
||||||
),
|
|
||||||
bitbang_spi: BitbangSpi::new(sclk_pin, mosi_pin, miso, cs_pin),
|
|
||||||
dma_channel,
|
dma_channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user