Move some implementation details out of GPIO (#2429)

* Move macros out of gpio

* Align S2 impl
This commit is contained in:
Dániel Buga 2024-10-30 16:11:48 +01:00 committed by GitHub
parent 3e42b76993
commit a8fedf0130
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 581 additions and 381 deletions

View File

@ -1122,312 +1122,6 @@ macro_rules! gpio {
};
}
#[cfg(xtensa)]
#[doc(hidden)]
#[macro_export]
macro_rules! rtcio_analog {
( @ignore $rue:literal ) => {};
(
$pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:literal)?
) => {
impl $crate::gpio::RtcPin for GpioPin<$pin_num>
{
fn rtc_number(&self) -> u8 {
$rtc_pin
}
/// Set the RTC properties of the pin. If `mux` is true then then pin is
/// routed to RTC, when false it is routed to IO_MUX.
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
use $crate::peripherals::RTC_IO;
let rtcio = unsafe{ &*RTC_IO::ptr() };
$crate::gpio::enable_iomux_clk_gate();
// disable input
paste::paste!{
rtcio.$pin_reg.modify(|_,w| unsafe {
w.[<$prefix fun_ie>]().bit(input_enable);
w.[<$prefix mux_sel>]().bit(mux);
w.[<$prefix fun_sel>]().bits(func as u8)
});
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
let rtc_ctrl = unsafe { $crate::peripherals::LPWR::steal() };
cfg_if::cfg_if! {
if #[cfg(esp32)] {
let pad_hold = rtc_ctrl.hold_force();
} else {
let pad_hold = rtc_ctrl.pad_hold();
}
};
pad_hold.modify(|_, w| w.$hold().bit(enable));
}
}
$(
// FIXME: replace with $(ignore($rue)) once stable
$crate::rtcio_analog!(@ignore $rue);
impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num>
{
fn rtcio_pullup(&mut self, enable: bool) {
let rtcio = unsafe { $crate::peripherals::RTC_IO::steal() };
paste::paste! {
rtcio.$pin_reg.modify(|_, w| w.[< $prefix rue >]().bit(enable));
}
}
fn rtcio_pulldown(&mut self, enable: bool) {
let rtcio = unsafe { $crate::peripherals::RTC_IO::steal() };
paste::paste! {
rtcio.$pin_reg.modify(|_, w| w.[< $prefix rde >]().bit(enable));
}
}
}
)?
#[cfg(any(adc, dac))]
impl $crate::gpio::AnalogPin for GpioPin<$pin_num> {
/// Configures the pin for analog mode.
fn set_analog(&self, _: $crate::private::Internal) {
let rtcio = unsafe{ &*$crate::peripherals::RTC_IO::ptr() };
#[cfg(esp32s2)]
$crate::gpio::enable_iomux_clk_gate();
// We need `paste` (and a [< >] in it) to rewrite the token stream to
// handle indexed pins.
paste::paste! {
// disable input
rtcio.$pin_reg.modify(|_,w| w.[<$prefix fun_ie>]().bit(false));
// disable output
rtcio.enable_w1tc().write(|w| unsafe { w.enable_w1tc().bits(1 << $rtc_pin) });
// disable open drain
rtcio.pin($rtc_pin).modify(|_,w| w.pad_driver().bit(false));
rtcio.$pin_reg.modify(|_,w| {
w.[<$prefix fun_ie>]().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.[<$prefix mux_sel>]().set_bit();
// Select function "RTC function 1" (GPIO) for analog use
unsafe { w.[<$prefix fun_sel>]().bits(0b00) };
// Disable pull-up and pull-down resistors on the pin, if it has them
$(
// FIXME: replace with $(ignore($rue)) once stable
$crate::rtcio_analog!( @ignore $rue );
w.[<$prefix rue>]().bit(false);
w.[<$prefix rde>]().bit(false);
)?
w
});
}
}
}
};
(
$( ( $pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:literal )? ) )+
) => {
$(
$crate::rtcio_analog!($pin_num, $rtc_pin, $pin_reg, $prefix, $hold $(, $rue )?);
)+
#[cfg(esp32)]
pub(crate) fn errata36(mut pin: AnyPin, pull_up: bool, pull_down: bool) {
use $crate::gpio::{Pin, RtcPinWithResistors};
let has_pullups = match pin.number() {
$(
$( $pin_num => $rue, )?
)+
_ => false,
};
if has_pullups {
pin.rtcio_pullup(pull_up);
pin.rtcio_pulldown(pull_down);
}
}
};
}
#[cfg(any(esp32c2, esp32c3))]
#[doc(hidden)]
#[macro_export]
macro_rules! rtc_pins {
( $( $pin_num:expr )+ ) => {
$(
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) {
let rtc_cntl = unsafe { &*$crate::peripherals::RTC_CNTL::ptr() };
cfg_if::cfg_if! {
if #[cfg(esp32c2)] {
let gpio_wakeup = rtc_cntl.cntl_gpio_wakeup();
} else {
let gpio_wakeup = rtc_cntl.gpio_wakeup();
}
}
paste::paste! {
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _wakeup_enable >]().bit(wakeup));
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _int_type >]().bits(level));
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
let rtc_cntl = unsafe { &*$crate::peripherals::RTC_CNTL::ptr() };
paste::paste! {
rtc_cntl.pad_hold().modify(|_, w| w.[< gpio_pin $pin_num _hold >]().bit(enable));
}
}
}
impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num> {
fn rtcio_pullup(&mut self, enable: bool) {
let io_mux = unsafe { &*$crate::peripherals::IO_MUX::ptr() };
io_mux.gpio($pin_num).modify(|_, w| w.fun_wpu().bit(enable));
}
fn rtcio_pulldown(&mut self, enable: bool) {
let io_mux = unsafe { &*$crate::peripherals::IO_MUX::ptr() };
io_mux.gpio($pin_num).modify(|_, w| w.fun_wpd().bit(enable));
}
}
)+
};
}
#[doc(hidden)]
pub fn enable_iomux_clk_gate() {
cfg_if::cfg_if! {
if #[cfg(esp32s2)] {
let sensors = unsafe { &*crate::peripherals::SENS::ptr() };
sensors
.sar_io_mux_conf()
.modify(|_, w| w.iomux_clk_gate_en().set_bit());
} else if #[cfg(esp32s3)] {
let sensors = unsafe { &*crate::peripherals::SENS::ptr() };
sensors
.sar_peri_clk_gate_conf()
.modify(|_,w| w.iomux_clk_en().set_bit());
}
}
}
/// Common functionality for all touch pads
#[doc(hidden)]
#[macro_export]
macro_rules! touch {
(@pin_specific $touch_num:expr, true) => {
paste::paste! {
unsafe { &*RTC_IO::ptr() }.[< touch_pad $touch_num >]().write(|w| unsafe {
w.xpd().set_bit();
// clear input_enable
w.fun_ie().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.mux_sel().set_bit();
// Disable pull-up and pull-down resistors on the pin
w.rue().clear_bit();
w.rde().clear_bit();
w.tie_opt().clear_bit();
// Select function "RTC function 1" (GPIO) for analog use
w.fun_sel().bits(0b00)
});
}
};
(@pin_specific $touch_num:expr, false) => {
paste::paste! {
unsafe { &*RTC_IO::ptr() }.[< touch_pad $touch_num >]().write(|w| {
w.xpd().set_bit();
w.tie_opt().clear_bit()
});
}
};
(
$(
(
$touch_num:literal, $pin_num:literal, $rtc_pin:literal, $touch_out_reg:expr, $meas_field: expr, $touch_thres_reg:expr, $touch_thres_field:expr, $normal_pin:literal
)
)+
) => {
$(
impl $crate::gpio::TouchPin for GpioPin<$pin_num> {
fn set_touch(&self, _: $crate::private::Internal) {
use $crate::peripherals::{GPIO, RTC_IO, SENS};
let gpio = unsafe { &*GPIO::ptr() };
let rtcio = unsafe { &*RTC_IO::ptr() };
let sens = unsafe { &*SENS::ptr() };
// Pad to normal mode (not open-drain)
gpio.pin($rtc_pin).write(|w| w.pad_driver().clear_bit());
// clear output
rtcio
.enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << $rtc_pin) });
paste::paste! {
sens . $touch_thres_reg ()
.write(|w| unsafe {
w. $touch_thres_field ().bits(
0b0 // Default: 0 for esp32 gets overridden later anyway.
)
});
$crate::touch!( @pin_specific $touch_num, $normal_pin );
// enable the pin
sens.sar_touch_enable().modify(|r, w| unsafe {
w.touch_pad_worken().bits(
r.touch_pad_worken().bits() | ( 1 << [< $touch_num >] )
)
});
}
}
fn get_touch_measurement(&self, _: $crate::private::Internal) -> u16 {
paste::paste! {
unsafe { &* $crate::peripherals::SENS::ptr() }
. $touch_out_reg ()
.read()
. $meas_field ()
.bits()
}
}
fn get_touch_nr(&self, _: $crate::private::Internal) -> u8 {
$touch_num
}
fn set_threshold(&self, threshold: u16, _: $crate::private::Internal) {
paste::paste! {
unsafe { &* $crate::peripherals::SENS::ptr() }
. $touch_thres_reg ()
.write(|w| unsafe {
w. $touch_thres_field ().bits(threshold)
});
}
}
})+
};
}
/// GPIO output driver.
pub struct Output<'d, P = AnyPin> {
pin: Flex<'d, P>,
@ -2100,12 +1794,13 @@ fn is_listening(pin_num: u8) -> bool {
}
fn set_int_enable(gpio_num: u8, int_ena: u8, int_type: u8, wake_up_from_light_sleep: bool) {
let gpio = unsafe { GPIO::steal() };
gpio.pin(gpio_num as usize).modify(|_, w| unsafe {
w.int_ena().bits(int_ena);
w.int_type().bits(int_type);
w.wakeup_enable().bit(wake_up_from_light_sleep)
});
unsafe { GPIO::steal() }
.pin(gpio_num as usize)
.modify(|_, w| unsafe {
w.int_ena().bits(int_ena);
w.int_type().bits(int_type);
w.wakeup_enable().bit(wake_up_from_light_sleep)
});
}
#[ram]

View File

@ -527,6 +527,220 @@ pub enum OutputSignal {
MTDO,
}
macro_rules! rtcio_analog {
( @ignore $rue:literal ) => {};
(
$pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:literal)?
) => {
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
fn rtc_number(&self) -> u8 {
$rtc_pin
}
/// Set the RTC properties of the pin. If `mux` is true then then pin is
/// routed to RTC, when false it is routed to IO_MUX.
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
// disable input
paste::paste!{
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_,w| unsafe {
w.[<$prefix fun_ie>]().bit(input_enable);
w.[<$prefix mux_sel>]().bit(mux);
w.[<$prefix fun_sel>]().bits(func as u8)
});
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
unsafe { $crate::peripherals::LPWR::steal() }
.hold_force()
.modify(|_, w| w.$hold().bit(enable));
}
}
$(
// FIXME: replace with $(ignore($rue)) once stable
rtcio_analog!(@ignore $rue);
impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num> {
fn rtcio_pullup(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rue >]().bit(enable));
}
}
fn rtcio_pulldown(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rde >]().bit(enable));
}
}
}
)?
impl $crate::gpio::AnalogPin for GpioPin<$pin_num> {
/// Configures the pin for analog mode.
fn set_analog(&self, _: $crate::private::Internal) {
use $crate::gpio::RtcPin;
let rtcio = unsafe{ $crate::peripherals::RTC_IO::steal() };
paste::paste! {
// disable input
rtcio.$pin_reg.modify(|_,w| w.[<$prefix fun_ie>]().bit(false));
// disable output
rtcio.enable_w1tc().write(|w| unsafe { w.enable_w1tc().bits(1 << self.rtc_number()) });
// disable open drain
rtcio.pin(self.rtc_number() as usize).modify(|_,w| w.pad_driver().bit(false));
rtcio.$pin_reg.modify(|_,w| {
w.[<$prefix fun_ie>]().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.[<$prefix mux_sel>]().set_bit();
// Select function "RTC function 1" (GPIO) for analog use
unsafe { w.[<$prefix fun_sel>]().bits(0b00) };
// Disable pull-up and pull-down resistors on the pin, if it has them
$(
// FIXME: replace with $(ignore($rue)) once stable
rtcio_analog!( @ignore $rue );
w.[<$prefix rue>]().bit(false);
w.[<$prefix rde>]().bit(false);
)?
w
});
}
}
}
};
(
$( ( $pin_num:expr, $rtc_pin:expr, $pin_reg:expr, $prefix:pat, $hold:ident $(, $rue:literal )? ) )+
) => {
$(
rtcio_analog!($pin_num, $rtc_pin, $pin_reg, $prefix, $hold $(, $rue )?);
)+
pub(crate) fn errata36(mut pin: AnyPin, pull_up: bool, pull_down: bool) {
use $crate::gpio::{Pin, RtcPinWithResistors};
let has_pullups = match pin.number() {
$(
$( $pin_num => $rue, )?
)+
_ => false,
};
if has_pullups {
pin.rtcio_pullup(pull_up);
pin.rtcio_pulldown(pull_down);
}
}
};
}
/// Common functionality for all touch pads
macro_rules! touch {
(@pin_specific $touch_num:expr, true) => {
paste::paste! {
unsafe { RTC_IO::steal() }.[< touch_pad $touch_num >]().write(|w| unsafe {
w.xpd().set_bit();
// clear input_enable
w.fun_ie().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.mux_sel().set_bit();
// Disable pull-up and pull-down resistors on the pin
w.rue().clear_bit();
w.rde().clear_bit();
w.tie_opt().clear_bit();
// Select function "RTC function 1" (GPIO) for analog use
w.fun_sel().bits(0b00)
});
}
};
(@pin_specific $touch_num:expr, false) => {
paste::paste! {
unsafe { RTC_IO::steal() }.[< touch_pad $touch_num >]().write(|w| {
w.xpd().set_bit();
w.tie_opt().clear_bit()
});
}
};
(
$(
(
$touch_num:literal, $pin_num:literal, $touch_out_reg:expr, $touch_thres_reg:expr, $normal_pin:literal
)
)+
) => {
$(
impl $crate::gpio::TouchPin for GpioPin<$pin_num> {
fn set_touch(&self, _: $crate::private::Internal) {
use $crate::peripherals::{GPIO, RTC_IO, SENS};
use $crate::gpio::RtcPin;
let gpio = unsafe { GPIO::steal() };
let rtcio = unsafe { RTC_IO::steal() };
let sens = unsafe { SENS::steal() };
// Pad to normal mode (not open-drain)
gpio.pin(self.rtc_number() as usize).write(|w| w.pad_driver().clear_bit());
// clear output
rtcio
.enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << self.rtc_number()) });
paste::paste! {
sens . $touch_thres_reg ()
.write(|w| unsafe {
w. [<touch_out_th $touch_num>] ().bits(
0b0 // Default: 0 for esp32 gets overridden later anyway.
)
});
touch!( @pin_specific $touch_num, $normal_pin );
// enable the pin
sens.sar_touch_enable().modify(|r, w| unsafe {
w.touch_pad_worken().bits(
r.touch_pad_worken().bits() | ( 1 << $touch_num )
)
});
}
}
fn get_touch_measurement(&self, _: $crate::private::Internal) -> u16 {
paste::paste! {
unsafe { $crate::peripherals::SENS::steal() }
. $touch_out_reg ().read()
. [<touch_meas_out $touch_num>] ().bits()
}
}
fn get_touch_nr(&self, _: $crate::private::Internal) -> u8 {
$touch_num
}
fn set_threshold(&self, threshold: u16, _: $crate::private::Internal) {
paste::paste! {
unsafe { $crate::peripherals::SENS::steal() }
. $touch_thres_reg ()
.write(|w| unsafe {
w. [<touch_out_th $touch_num>] ().bits(threshold)
});
}
}
})+
};
}
crate::gpio! {
(0, [Input, Output, Analog, RtcIo, Touch] (5 => EMAC_TX_CLK) (1 => CLK_OUT1))
(1, [Input, Output] (5 => EMAC_RXD2) (0 => U0TXD 1 => CLK_OUT3))
@ -566,7 +780,7 @@ crate::gpio! {
(39, [Input, Analog, RtcIoInput])
}
crate::rtcio_analog! {
rtcio_analog! {
(36, 0, sensor_pads(), sense1_, sense1_hold_force )
(37, 1, sensor_pads(), sense2_, sense2_hold_force )
(38, 2, sensor_pads(), sense3_, sense3_hold_force )
@ -587,19 +801,19 @@ crate::rtcio_analog! {
(27, 17, touch_pad7(), "", touch_pad7_hold_force, true)
}
crate::touch! {
// touch_nr, pin_nr, rtc_pin, touch_out_reg, meas_field, touch_thres_reg, touch_thres_field, normal_pin
(0, 4, 10, sar_touch_out1, touch_meas_out0, sar_touch_thres1, touch_out_th0, true)
(1, 0, 11, sar_touch_out1, touch_meas_out1, sar_touch_thres1, touch_out_th1, true)
(2, 2, 12, sar_touch_out2, touch_meas_out2, sar_touch_thres2, touch_out_th2, true)
(3, 15, 13, sar_touch_out2, touch_meas_out3, sar_touch_thres2, touch_out_th3, true)
(4, 13, 14, sar_touch_out3, touch_meas_out4, sar_touch_thres3, touch_out_th4, true)
(5, 12, 15, sar_touch_out3, touch_meas_out5, sar_touch_thres3, touch_out_th5, true)
(6, 14, 16, sar_touch_out4, touch_meas_out6, sar_touch_thres4, touch_out_th6, true)
(7, 27, 17, sar_touch_out4, touch_meas_out7, sar_touch_thres4, touch_out_th7, true)
touch! {
// touch_nr, pin_nr, touch_out_reg, touch_thres_reg, normal_pin
(0, 4, sar_touch_out1, sar_touch_thres1, true)
(1, 0, sar_touch_out1, sar_touch_thres1, true)
(2, 2, sar_touch_out2, sar_touch_thres2, true)
(3, 15, sar_touch_out2, sar_touch_thres2, true)
(4, 13, sar_touch_out3, sar_touch_thres3, true)
(5, 12, sar_touch_out3, sar_touch_thres3, true)
(6, 14, sar_touch_out4, sar_touch_thres4, true)
(7, 27, sar_touch_out4, sar_touch_thres4, true)
// ---
(8, 33, 8, sar_touch_out5, touch_meas_out8, sar_touch_thres5, touch_out_th8, false)
(9, 32, 9, sar_touch_out5, touch_meas_out9, sar_touch_thres5, touch_out_th9, false)
(8, 33, sar_touch_out5, sar_touch_thres5, false)
(9, 32, sar_touch_out5, sar_touch_thres5, false)
}
#[derive(Clone, Copy)]
@ -612,12 +826,12 @@ impl InterruptStatusRegisterAccess {
pub(crate) fn interrupt_status_read(self) -> u32 {
match self {
Self::Bank0 => match crate::get_core() {
crate::Cpu::ProCpu => unsafe { &*GPIO::PTR }.pcpu_int().read().bits(),
crate::Cpu::AppCpu => unsafe { &*GPIO::PTR }.acpu_int().read().bits(),
crate::Cpu::ProCpu => unsafe { GPIO::steal() }.pcpu_int().read().bits(),
crate::Cpu::AppCpu => unsafe { GPIO::steal() }.acpu_int().read().bits(),
},
Self::Bank1 => match crate::get_core() {
crate::Cpu::ProCpu => unsafe { &*GPIO::PTR }.pcpu_int1().read().bits(),
crate::Cpu::AppCpu => unsafe { &*GPIO::PTR }.acpu_int1().read().bits(),
crate::Cpu::ProCpu => unsafe { GPIO::steal() }.pcpu_int1().read().bits(),
crate::Cpu::AppCpu => unsafe { GPIO::steal() }.acpu_int1().read().bits(),
},
}
}

View File

@ -171,6 +171,47 @@ pub enum OutputSignal {
GPIO = 128,
}
macro_rules! rtc_pins {
( $( $pin_num:expr )+ ) => {
$(
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) {
let rtc_cntl = unsafe { $crate::peripherals::RTC_CNTL::steal() };
let gpio_wakeup = rtc_cntl.cntl_gpio_wakeup();
paste::paste! {
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _wakeup_enable >]().bit(wakeup));
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _int_type >]().bits(level));
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_CNTL::steal() }
.pad_hold().modify(|_, w| w.[< gpio_pin $pin_num _hold >]().bit(enable));
}
}
}
)+
};
}
impl<const N: u8> crate::gpio::RtcPinWithResistors for GpioPin<N>
where
Self: crate::gpio::RtcPin,
{
fn rtcio_pullup(&mut self, enable: bool) {
unsafe { crate::peripherals::IO_MUX::steal() }
.gpio(N as usize)
.modify(|_, w| w.fun_wpu().bit(enable));
}
fn rtcio_pulldown(&mut self, enable: bool) {
unsafe { crate::peripherals::IO_MUX::steal() }
.gpio(N as usize)
.modify(|_, w| w.fun_wpd().bit(enable));
}
}
crate::gpio! {
(0, [Input, Output, Analog, RtcIo])
(1, [Input, Output, Analog, RtcIo])
@ -188,7 +229,7 @@ crate::gpio! {
(20, [Input, Output] (0 => U0RXD) ())
}
crate::rtc_pins! {
rtc_pins! {
0
1
2

View File

@ -198,6 +198,48 @@ pub enum OutputSignal {
GPIO = 128,
}
macro_rules! rtc_pins {
( $( $pin_num:expr )+ ) => {
$(
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) {
let rtc_cntl = unsafe { $crate::peripherals::RTC_CNTL::steal() };
let gpio_wakeup = rtc_cntl.gpio_wakeup();
paste::paste! {
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _wakeup_enable >]().bit(wakeup));
gpio_wakeup.modify(|_, w| w.[< gpio_pin $pin_num _int_type >]().bits(level));
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_CNTL::steal() }
.pad_hold().modify(|_, w| w.[< gpio_pin $pin_num _hold >]().bit(enable));
}
}
}
)+
};
}
impl<const N: u8> crate::gpio::RtcPinWithResistors for GpioPin<N>
where
Self: crate::gpio::RtcPin,
{
fn rtcio_pullup(&mut self, enable: bool) {
unsafe { crate::peripherals::IO_MUX::steal() }
.gpio(N as usize)
.modify(|_, w| w.fun_wpu().bit(enable));
}
fn rtcio_pulldown(&mut self, enable: bool) {
unsafe { crate::peripherals::IO_MUX::steal() }
.gpio(N as usize)
.modify(|_, w| w.fun_wpd().bit(enable));
}
}
crate::gpio! {
(0, [Input, Output, Analog, RtcIo])
(1, [Input, Output, Analog, RtcIo])
@ -224,7 +266,7 @@ crate::gpio! {
}
// RTC pins 0 through 5 (inclusive) support GPIO wakeup
crate::rtc_pins! {
rtc_pins! {
0
1
2

View File

@ -314,6 +314,104 @@ pub enum OutputSignal {
GPIO = 256,
}
macro_rules! rtcio_analog {
( @ignore $rue:literal ) => {};
(
$pin_num:expr, $pin_reg:expr, $prefix:pat, $hold:ident
) => {
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
fn rtc_number(&self) -> u8 {
$pin_num
}
/// Set the RTC properties of the pin. If `mux` is true then then pin is
/// routed to RTC, when false it is routed to IO_MUX.
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
enable_iomux_clk_gate();
// disable input
paste::paste!{
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_,w| unsafe {
w.[<$prefix fun_ie>]().bit(input_enable);
w.[<$prefix mux_sel>]().bit(mux);
w.[<$prefix fun_sel>]().bits(func as u8)
});
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
unsafe { $crate::peripherals::LPWR::steal() }
.pad_hold()
.modify(|_, w| w.$hold().bit(enable));
}
}
impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num>
{
fn rtcio_pullup(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rue >]().bit(enable));
}
}
fn rtcio_pulldown(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rde >]().bit(enable));
}
}
}
impl $crate::gpio::AnalogPin for GpioPin<$pin_num> {
/// Configures the pin for analog mode.
fn set_analog(&self, _: $crate::private::Internal) {
use $crate::gpio::RtcPin;
enable_iomux_clk_gate();
let rtcio = unsafe{ $crate::peripherals::RTC_IO::steal() };
paste::paste! {
// disable input
rtcio.$pin_reg.modify(|_,w| w.[<$prefix fun_ie>]().bit(false));
// disable output
rtcio.enable_w1tc().write(|w| unsafe { w.enable_w1tc().bits(1 << self.rtc_number()) });
// disable open drain
rtcio.pin(self.rtc_number() as usize).modify(|_,w| w.pad_driver().bit(false));
rtcio.$pin_reg.modify(|_,w| {
w.[<$prefix fun_ie>]().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.[<$prefix mux_sel>]().set_bit();
// Select function "RTC function 1" (GPIO) for analog use
unsafe { w.[<$prefix fun_sel>]().bits(0b00) };
// Disable pull-up and pull-down resistors on the pin
w.[<$prefix rue>]().bit(false);
w.[<$prefix rde>]().bit(false);
w
});
}
}
}
};
(
$( ( $pin_num:expr, $pin_reg:expr, $prefix:pat, $hold:ident ) )+
) => {
$(
rtcio_analog!($pin_num, $pin_reg, $prefix, $hold);
)+
};
}
crate::gpio! {
(0, [Input, Output, Analog, RtcIo])
(1, [Input, Output, Analog, RtcIo])
@ -361,29 +459,29 @@ crate::gpio! {
(46, [Input, Output])
}
crate::rtcio_analog! {
( 0, 0, touch_pad(0), "", touch_pad0_hold, true)
( 1, 1, touch_pad(1), "", touch_pad1_hold, true)
( 2, 2, touch_pad(2), "", touch_pad2_hold, true)
( 3, 3, touch_pad(3), "", touch_pad3_hold, true)
( 4, 4, touch_pad(4), "", touch_pad4_hold, true)
( 5, 5, touch_pad(5), "", touch_pad5_hold, true)
( 6, 6, touch_pad(6), "", touch_pad6_hold, true)
( 7, 7, touch_pad(7), "", touch_pad7_hold, true)
( 8, 8, touch_pad(8), "", touch_pad8_hold, true)
( 9, 9, touch_pad(9), "", touch_pad9_hold, true)
(10, 10, touch_pad(10), "", touch_pad10_hold, true)
(11, 11, touch_pad(11), "", touch_pad11_hold, true)
(12, 12, touch_pad(12), "", touch_pad12_hold, true)
(13, 13, touch_pad(13), "", touch_pad13_hold, true)
(14, 14, touch_pad(14), "", touch_pad14_hold, true)
(15, 15, xtal_32p_pad(), x32p_, x32p_hold, true)
(16, 16, xtal_32n_pad(), x32n_, x32n_hold, true)
(17, 17, pad_dac1(), "", pdac1_hold, true)
(18, 18, pad_dac2(), "", pdac2_hold, true)
(19, 19, rtc_pad19(), "", pad19_hold, true)
(20, 20, rtc_pad20(), "", pad20_hold, true)
(21, 21, rtc_pad21(), "", pad21_hold, true)
rtcio_analog! {
( 0, touch_pad(0), "", touch_pad0_hold )
( 1, touch_pad(1), "", touch_pad1_hold )
( 2, touch_pad(2), "", touch_pad2_hold )
( 3, touch_pad(3), "", touch_pad3_hold )
( 4, touch_pad(4), "", touch_pad4_hold )
( 5, touch_pad(5), "", touch_pad5_hold )
( 6, touch_pad(6), "", touch_pad6_hold )
( 7, touch_pad(7), "", touch_pad7_hold )
( 8, touch_pad(8), "", touch_pad8_hold )
( 9, touch_pad(9), "", touch_pad9_hold )
(10, touch_pad(10), "", touch_pad10_hold)
(11, touch_pad(11), "", touch_pad11_hold)
(12, touch_pad(12), "", touch_pad12_hold)
(13, touch_pad(13), "", touch_pad13_hold)
(14, touch_pad(14), "", touch_pad14_hold)
(15, xtal_32p_pad(), x32p_, x32p_hold )
(16, xtal_32n_pad(), x32n_, x32n_hold )
(17, pad_dac1(), "", pdac1_hold )
(18, pad_dac2(), "", pdac2_hold )
(19, rtc_pad19(), "", pad19_hold )
(20, rtc_pad20(), "", pad20_hold )
(21, rtc_pad21(), "", pad21_hold )
}
#[derive(Clone, Copy)]
@ -395,8 +493,8 @@ pub(crate) enum InterruptStatusRegisterAccess {
impl InterruptStatusRegisterAccess {
pub(crate) fn interrupt_status_read(self) -> u32 {
match self {
Self::Bank0 => unsafe { &*GPIO::PTR }.pcpu_int().read().bits(),
Self::Bank1 => unsafe { &*GPIO::PTR }.pcpu_int1().read().bits(),
Self::Bank0 => unsafe { GPIO::steal() }.pcpu_int().read().bits(),
Self::Bank1 => unsafe { GPIO::steal() }.pcpu_int1().read().bits(),
}
}
}
@ -404,3 +502,9 @@ impl InterruptStatusRegisterAccess {
// implement marker traits on USB pins
impl crate::otg_fs::UsbDm for GpioPin<19> {}
impl crate::otg_fs::UsbDp for GpioPin<20> {}
fn enable_iomux_clk_gate() {
unsafe { crate::peripherals::SENS::steal() }
.sar_io_mux_conf()
.modify(|_, w| w.iomux_clk_gate_en().set_bit());
}

View File

@ -345,6 +345,104 @@ pub enum OutputSignal {
GPIO = 256,
}
macro_rules! rtcio_analog {
( @ignore $rue:literal ) => {};
(
$pin_num:expr, $pin_reg:expr, $prefix:pat, $hold:ident
) => {
impl $crate::gpio::RtcPin for GpioPin<$pin_num> {
fn rtc_number(&self) -> u8 {
$pin_num
}
/// Set the RTC properties of the pin. If `mux` is true then then pin is
/// routed to RTC, when false it is routed to IO_MUX.
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
enable_iomux_clk_gate();
// disable input
paste::paste!{
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_,w| unsafe {
w.[<$prefix fun_ie>]().bit(input_enable);
w.[<$prefix mux_sel>]().bit(mux);
w.[<$prefix fun_sel>]().bits(func as u8)
});
}
}
fn rtcio_pad_hold(&mut self, enable: bool) {
unsafe { $crate::peripherals::LPWR::steal() }
.pad_hold()
.modify(|_, w| w.$hold().bit(enable));
}
}
impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num>
{
fn rtcio_pullup(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rue >]().bit(enable));
}
}
fn rtcio_pulldown(&mut self, enable: bool) {
paste::paste! {
unsafe { $crate::peripherals::RTC_IO::steal() }
.$pin_reg.modify(|_, w| w.[< $prefix rde >]().bit(enable));
}
}
}
impl $crate::gpio::AnalogPin for GpioPin<$pin_num> {
/// Configures the pin for analog mode.
fn set_analog(&self, _: $crate::private::Internal) {
use $crate::gpio::RtcPin;
enable_iomux_clk_gate();
let rtcio = unsafe{ $crate::peripherals::RTC_IO::steal() };
paste::paste! {
// disable input
rtcio.$pin_reg.modify(|_,w| w.[<$prefix fun_ie>]().bit(false));
// disable output
rtcio.enable_w1tc().write(|w| unsafe { w.enable_w1tc().bits(1 << self.rtc_number()) });
// disable open drain
rtcio.pin(self.rtc_number() as usize).modify(|_,w| w.pad_driver().bit(false));
rtcio.$pin_reg.modify(|_,w| {
w.[<$prefix fun_ie>]().clear_bit();
// Connect pin to analog / RTC module instead of standard GPIO
w.[<$prefix mux_sel>]().set_bit();
// Select function "RTC function 1" (GPIO) for analog use
unsafe { w.[<$prefix fun_sel>]().bits(0b00) };
// Disable pull-up and pull-down resistors on the pin
w.[<$prefix rue>]().bit(false);
w.[<$prefix rde>]().bit(false);
w
});
}
}
}
};
(
$( ( $pin_num:expr, $pin_reg:expr, $prefix:pat, $hold:ident ) )+
) => {
$(
rtcio_analog!($pin_num, $pin_reg, $prefix, $hold);
)+
};
}
crate::gpio! {
(0, [Input, Output, Analog, RtcIo])
(1, [Input, Output, Analog, RtcIo])
@ -393,29 +491,29 @@ crate::gpio! {
(48, [Input, Output])
}
crate::rtcio_analog! {
( 0, 0, touch_pad(0), "", touch_pad0_hold, true)
( 1, 1, touch_pad(1), "", touch_pad1_hold, true)
( 2, 2, touch_pad(2), "", touch_pad2_hold, true)
( 3, 3, touch_pad(3), "", touch_pad3_hold, true)
( 4, 4, touch_pad(4), "", touch_pad4_hold, true)
( 5, 5, touch_pad(5), "", touch_pad5_hold, true)
( 6, 6, touch_pad(6), "", touch_pad6_hold, true)
( 7, 7, touch_pad(7), "", touch_pad7_hold, true)
( 8, 8, touch_pad(8), "", touch_pad8_hold, true)
( 9, 9, touch_pad(9), "", touch_pad9_hold, true)
(10, 10, touch_pad(10), "", touch_pad10_hold, true)
(11, 11, touch_pad(11), "", touch_pad11_hold, true)
(12, 12, touch_pad(12), "", touch_pad12_hold, true)
(13, 13, touch_pad(13), "", touch_pad13_hold, true)
(14, 14, touch_pad(14), "", touch_pad14_hold, true)
(15, 15, xtal_32p_pad(), x32p_, x32p_hold, true)
(16, 16, xtal_32n_pad(), x32n_, x32n_hold, true)
(17, 17, pad_dac1(), pdac1_, pdac1_hold, true)
(18, 18, pad_dac2(), pdac2_, pdac2_hold, true)
(19, 19, rtc_pad19(), "", pad19_hold, true)
(20, 20, rtc_pad20(), "", pad20_hold, true)
(21, 21, rtc_pad21(), "", pad21_hold, true)
rtcio_analog! {
( 0, touch_pad(0), "", touch_pad0_hold )
( 1, touch_pad(1), "", touch_pad1_hold )
( 2, touch_pad(2), "", touch_pad2_hold )
( 3, touch_pad(3), "", touch_pad3_hold )
( 4, touch_pad(4), "", touch_pad4_hold )
( 5, touch_pad(5), "", touch_pad5_hold )
( 6, touch_pad(6), "", touch_pad6_hold )
( 7, touch_pad(7), "", touch_pad7_hold )
( 8, touch_pad(8), "", touch_pad8_hold )
( 9, touch_pad(9), "", touch_pad9_hold )
(10, touch_pad(10), "", touch_pad10_hold)
(11, touch_pad(11), "", touch_pad11_hold)
(12, touch_pad(12), "", touch_pad12_hold)
(13, touch_pad(13), "", touch_pad13_hold)
(14, touch_pad(14), "", touch_pad14_hold)
(15, xtal_32p_pad(), x32p_, x32p_hold )
(16, xtal_32n_pad(), x32n_, x32n_hold )
(17, pad_dac1(), pdac1_, pdac1_hold )
(18, pad_dac2(), pdac2_, pdac2_hold )
(19, rtc_pad19(), "", pad19_hold )
(20, rtc_pad20(), "", pad20_hold )
(21, rtc_pad21(), "", pad21_hold )
}
// Whilst the S3 is a dual core chip, it shares the enable registers between
@ -429,8 +527,8 @@ pub(crate) enum InterruptStatusRegisterAccess {
impl InterruptStatusRegisterAccess {
pub(crate) fn interrupt_status_read(self) -> u32 {
match self {
Self::Bank0 => unsafe { &*GPIO::PTR }.pcpu_int().read().bits(),
Self::Bank1 => unsafe { &*GPIO::PTR }.pcpu_int1().read().bits(),
Self::Bank0 => unsafe { GPIO::steal() }.pcpu_int().read().bits(),
Self::Bank1 => unsafe { GPIO::steal() }.pcpu_int1().read().bits(),
}
}
}
@ -438,3 +536,9 @@ impl InterruptStatusRegisterAccess {
// implement marker traits on USB pins
impl crate::otg_fs::UsbDm for GpioPin<19> {}
impl crate::otg_fs::UsbDp for GpioPin<20> {}
fn enable_iomux_clk_gate() {
unsafe { crate::peripherals::SENS::steal() }
.sar_peri_clk_gate_conf()
.modify(|_, w| w.iomux_clk_en().set_bit());
}