diff --git a/.vscode/settings.json b/.vscode/settings.json index c8bd4d59837..a7ba43bd94c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { + "rust-analyzer.cargo.features": [ + "esp32c3" + ], "editor.formatOnSave": true, "rust-analyzer.checkOnSave.allTargets": false -} +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 5703a08121e..dcf84784c50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,5 @@ members = [ "esp32-hal", "esp32c3-hal", "esp32s2-hal", - "esp32s3-hal", + "esp32s3-hal" ] diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 9e7134008e1..52ed4433f05 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2018" [dependencies] +paste = "1.0.6" embedded-hal = { version = "0.2", features = ["unproven"] } nb = "1.0" riscv = { version = "0.7", optional = true } @@ -12,7 +13,7 @@ xtensa-lx = { version = "0.4", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32_pac = { package = "esp32", git = "https://github.com/jessebraham/esp32.git", branch = "develop", optional = true } +esp32_pac = { package = "esp32", git = "https://github.com/jessebraham/esp32.git", branch = "develop", optional = true } esp32c3_pac = { package = "esp32c3", git = "https://github.com/jessebraham/esp32c3.git", branch = "develop", optional = true } esp32s2_pac = { package = "esp32s2", git = "https://github.com/jessebraham/esp32s2.git", branch = "develop", optional = true } esp32s3_pac = { package = "esp32s3", git = "https://github.com/jessebraham/esp32s3.git", branch = "develop", optional = true } diff --git a/esp-hal-common/src/gpio/mod.rs b/esp-hal-common/src/gpio/mod.rs new file mode 100644 index 00000000000..484b12f7c70 --- /dev/null +++ b/esp-hal-common/src/gpio/mod.rs @@ -0,0 +1,758 @@ +pub use crate::prelude::*; +pub use paste::paste; + +#[macro_export] +macro_rules! impl_output { + ( + $gpio_function:ident, + $pxi:ident: + ( + $pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_set:ident, $out_en_clear:ident, + $out_set:ident, $out_clear:ident, $out_reg:ident + ) + $( ,( $( $af_signal:ident: $af:ident ),* ))? + ) => { + impl embedded_hal::digital::v2::OutputPin for $pxi> { + type Error = Infallible; + + fn set_high(&mut self) -> Result<(), Self::Error> { + unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) }; + Ok(()) + } + + fn set_low(&mut self) -> Result<(), Self::Error> { + unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) }; + Ok(()) + } + } + + impl embedded_hal::digital::v2::StatefulOutputPin for $pxi> { + fn is_set_high(&self) -> Result { + unsafe { Ok((*GPIO::ptr()).$out_reg.read().bits() & (1 << $bit) != 0) } + } + + fn is_set_low(&self) -> Result { + Ok(!self.is_set_high()?) + } + } + + impl embedded_hal::digital::v2::ToggleableOutputPin for $pxi> { + type Error = Infallible; + + fn toggle(&mut self) -> Result<(), Self::Error> { + if self.is_set_high()? { + Ok(self.set_low()?) + } else { + Ok(self.set_high()?) + } + } + } + + impl $pxi { + pub fn into_pull_up_input(self) -> $pxi> { + self.init_input(false, false); + $pxi { _mode: PhantomData } + } + + pub fn into_pull_down_input(self) -> $pxi> { + self.init_input(true, false); + $pxi { _mode: PhantomData } + } + + fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { + let gpio = unsafe { &*GPIO::ptr() }; + let iomux = unsafe { &*IO_MUX::ptr() }; + + gpio.$out_en_set.write(|w| unsafe { w.bits(1 << $bit) }); + gpio.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(open_drain)); + gpio.func_out_sel_cfg[$pin_num] + .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); + + paste! { + iomux.$iomux_reg.modify(|_, w| unsafe { + w.mcu_sel() + .bits(alternate as u8) + .fun_ie() + .clear_bit() + .fun_wpd() + .clear_bit() + .fun_wpu() + .clear_bit() + .fun_drv() + .bits(DriveStrength::I20mA as u8) + .slp_sel() + .clear_bit() + }); + } + + + } + + pub fn into_push_pull_output(self) -> $pxi> { + self.init_output(AlternateFunction::$gpio_function, false); + $pxi { _mode: PhantomData } + } + + pub fn into_open_drain_output(self) -> $pxi> { + self.init_output(AlternateFunction::$gpio_function, true); + $pxi { _mode: PhantomData } + } + + pub fn into_alternate_1(self) -> $pxi> { + self.init_output(AlternateFunction::Function1, false); + $pxi { _mode: PhantomData } + } + + pub fn into_alternate_2(self) -> $pxi> { + self.init_output(AlternateFunction::Function2, false); + $pxi { _mode: PhantomData } + } + } + + impl OutputPin for $pxi { + fn set_to_open_drain_output(&mut self) -> &mut Self { + self.init_output(AlternateFunction::$gpio_function, true); + self + } + + fn set_to_push_pull_output(&mut self) -> &mut Self { + self.init_output(AlternateFunction::$gpio_function, false); + self + } + + fn enable_output(&mut self, on: bool) -> &mut Self { + if on { + unsafe { &*GPIO::ptr() } + .$out_en_set + .write(|w| unsafe { w.bits(1 << $bit) }); + } else { + unsafe { &*GPIO::ptr() } + .$out_en_clear + .write(|w| unsafe { w.bits(1 << $bit) }); + } + self + } + + fn set_output_high(&mut self, high: bool) -> &mut Self { + if high { + unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) }; + } else { + unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) }; + } + self + } + + fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) }); + } + self + } + + fn enable_open_drain(&mut self, on: bool) -> &mut Self { + unsafe { &*GPIO::ptr() }.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(on)); + self + } + + fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.mcu_wpu().bit(on)); + } + self + } + + fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { + paste!{ + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.mcu_wpd().bit(on)); + } + self + } + + fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.mcu_oe().bit(on)); + } + self + } + + fn connect_peripheral_to_output_with_options( + &mut self, + signal: OutputSignal, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + force_via_gpio_mux: bool, + ) -> &mut Self { + let af = if force_via_gpio_mux { + AlternateFunction::$gpio_function + } else { + match signal { + $( $( + OutputSignal::$af_signal => AlternateFunction::$af, + )* )? + _ => AlternateFunction::$gpio_function + } + }; + + if af == AlternateFunction::$gpio_function && signal as usize > OUTPUT_SIGNAL_MAX as usize { + panic!("Cannot connect this peripheral to GPIO"); + } + + self.set_alternate_function(af); + + let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { signal as OutputSignalType } else { OUTPUT_SIGNAL_MAX }; + + unsafe { &*GPIO::ptr() }.func_out_sel_cfg[$pin_num].modify(|_, w| unsafe { + w + .out_sel().bits(clipped_signal) + .inv_sel().bit(invert) + .oen_sel().bit(enable_from_gpio) + .oen_inv_sel().bit(invert_enable) + }); + + self + } + + fn internal_pull_up(&mut self, on: bool) -> &mut Self { + paste!{ + unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpu().bit(on)); + } + self + } + + fn internal_pull_down(&mut self, on: bool) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpd().bit(on)); + } + self + } + } + }; +} + +#[macro_export] +macro_rules! impl_input { + ($gpio_function:ident, + $pxi:ident: + ($pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_clear:ident, $reg:ident, $reader:ident, + $status_w1tc:ident, $pcpu_int:ident, $pcpu_nmi:ident, $acpu_int:ident, $acpu_nmi:ident + ) $( ,( $( $af_signal:ident : $af:ident ),* ))? + ) => { + impl embedded_hal::digital::v2::InputPin for $pxi> { + type Error = Infallible; + + fn is_high(&self) -> Result { + Ok(unsafe { &*GPIO::ptr() }.$reg.read().$reader().bits() & (1 << $bit) != 0) + } + + fn is_low(&self) -> Result { + Ok(!self.is_high()?) + } + } + + impl $pxi { + fn init_input(&self, pull_down: bool, pull_up: bool) { + let gpio = unsafe { &*GPIO::ptr() }; + let iomux = unsafe { &*IO_MUX::ptr() }; + + + gpio.$out_en_clear + .write(|w| unsafe { w.bits(1 << $bit) }); + + gpio.func_out_sel_cfg[$pin_num] + .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); + + + paste! { + iomux.$iomux_reg.modify(|_, w| unsafe { + w.mcu_sel() + .bits(2) + .fun_ie() + .set_bit() + .fun_wpd() + .bit(pull_down) + .fun_wpu() + .bit(pull_up) + .slp_sel() + .clear_bit() + }); + } + } + + pub fn into_floating_input(self) -> $pxi> { + self.init_input(false, false); + $pxi { _mode: PhantomData } + } + } + + impl InputPin for $pxi { + fn set_to_input(&mut self) -> &mut Self { + self.init_input(false, false); + self + } + + fn enable_input(&mut self, on: bool) -> &mut Self { + paste!{ + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.fun_ie().bit(on)); + } + self + } + + fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.mcu_ie().bit(on)); + } + self + } + + fn is_input_high(&mut self) -> bool { + unsafe { &*GPIO::ptr() }.$reg.read().$reader().bits() & (1 << $bit) != 0 + } + + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + ) -> &mut Self { + + let af = if force_via_gpio_mux + { + AlternateFunction::$gpio_function + } + else { + match signal { + $( $( + InputSignal::$af_signal => AlternateFunction::$af, + )* )? + _ => AlternateFunction::$gpio_function + } + }; + + if af == AlternateFunction::$gpio_function && signal as usize > INPUT_SIGNAL_MAX as usize { + panic!("Cannot connect GPIO to this peripheral"); + } + + self.set_alternate_function(af); + + if (signal as usize) <= INPUT_SIGNAL_MAX as usize { + unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(invert) + .in_sel() + .bits($pin_num) + }); + } + self + } + } + + impl Pin for $pxi { + fn sleep_mode(&mut self, on: bool) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| w.slp_sel().bit(on)); + } + self + } + + fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self { + paste! { + unsafe { &*IO_MUX::ptr() } + .$iomux_reg + .modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) }); + } + self + } + + fn listen_with_options(&mut self, event: Event, + int_enable: bool, nmi_enable: bool, + wake_up_from_light_sleep: bool + ) { + if wake_up_from_light_sleep { + match event { + Event::AnyEdge | Event::RisingEdge | Event::FallingEdge => { + panic!("Edge triggering is not supported for wake-up from light sleep"); + }, + _ => {} + } + } + unsafe { + (&*GPIO::ptr()).pin[$pin_num].modify(|_, w| + w + .pin_int_ena().bits(int_enable as u8 | ((nmi_enable as u8) << 1)) + .pin_int_type().bits(event as u8) + .pin_wakeup_enable().bit(wake_up_from_light_sleep) + ); + } + } + + fn unlisten(&mut self) { + unsafe { (&*GPIO::ptr()).pin[$pin_num].modify(|_, w| + w.pin_int_ena().bits(0).pin_int_type().bits(0).pin_int_ena().bits(0) ); + } + } + + fn clear_interrupt(&mut self) { + unsafe {&*GPIO::ptr()}.$status_w1tc.write(|w| + unsafe {w.bits(1 << $bit)}) + } + + fn is_pcore_interrupt_set(&mut self) -> bool { + (unsafe {&*GPIO::ptr()}.$pcpu_int.read().bits() & (1 << $bit)) !=0 + } + + fn is_pcore_non_maskable_interrupt_set(&mut self) -> bool { + (unsafe {&*GPIO::ptr()}.$pcpu_nmi.read().bits() & (1 << $bit)) !=0 + } + + fn is_acore_interrupt_set(&mut self) -> bool { + (unsafe {&*GPIO::ptr()}.$acpu_int.read().bits() & (1 << $bit)) !=0 + } + + fn is_acore_non_maskable_interrupt_set(&mut self) -> bool { + (unsafe {&*GPIO::ptr()}.$acpu_nmi.read().bits() & (1 << $bit)) !=0 + } + + fn enable_hold(&mut self, _on: bool) { + + + todo!(); + } + } + }; +} + +#[macro_export] +macro_rules! impl_pin_wrap { + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, SingleCore + $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? + ) => { + impl_input!($gpio_function, $pxi: ($pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next, + status_w1tc, pcpu_int, pcpu_nmi_int, pcpu_int, pcpu_nmi_int) + $( ,( $( $af_input_signal: $af_input ),* ) )? ); + }; + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, SingleCore + $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? + ) => { + impl_input!($gpio_function, $pxi: ($pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next, + status1_w1tc, pcpu_int1, pcpu_nmi_int1, pcpu_int1, pcpu_nmi_int1) + $( ,( $( $af_input_signal: $af_input ),* ) )? ); + }; + + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, DualCore + $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? + ) => { + impl_input!($gpio_function, $pxi: ($pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next, + status_w1tc, pcpu_int, pcpu_nmi_int, acpu_int, acpu_nmi_int) + $( ,( $( $af_input_signal: $af_input ),* ) )? ); + }; + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, DualCore + $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? + ) => { + impl_input!($gpio_function, $pxi: ($pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next, + status1_w1tc, pcpu_int1, pcpu_nmi_int1, acpu_int1, acpu_nmi_int1) + $( ,( $( $af_input_signal: $af_input ),* ) )? ); + }; +} + +#[macro_export] +macro_rules! impl_output_wrap { + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank0 + $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? + ) => { + impl_output!($gpio_function, $pxi: + ($pin_num, $iomux_reg, $pin_num % 32, enable_w1ts, enable_w1tc, out_w1ts, out_w1tc, out) + + $( ,( $( $af_output_signal: $af_output ),* ) )? ); + }; + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank1 + $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? + ) => { + impl_output!($gpio_function, $pxi: + ($pin_num, $iomux_reg, $pin_num % 32, enable1_w1ts, enable1_w1tc, out1_w1ts, out1_w1tc, out1) + + $( ,( $( $af_output_signal: $af_output ),* ) )? ); + }; + + ($gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, $bank:ident + $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? + ) => { + }; +} + +#[macro_export] +macro_rules! gpio { + ( $gpio_function:ident, + $cores:ident, + $($pxi:ident: ($pname:ident, $pin_num:literal, $iomux_reg:expr, $type:ident, $rtc:tt, $bank:ident ), + $( + ( $( $af_input_signal:ident: $af_input:ident ),* ), + $( + ( $( $af_output_signal:ident: $af_output:ident ),* ), + )? + )? + )+ ) => { + use core::{convert::Infallible, marker::PhantomData}; + use embedded_hal::digital::v2::{OutputPin as _, StatefulOutputPin as _}; + use crate::pac::{GPIO, IO_MUX}; + + #[allow(dead_code)] + pub struct IO { + io_mux: IO_MUX, + pub pins: Pins, + } + + impl IO { + pub fn new(gpio: GPIO, io_mux: IO_MUX) -> Self { + let pins = gpio.split(); + let io = IO { io_mux, pins }; + + io + } + } + + pub trait GpioExt { + type Parts; + + fn split(self) -> Self::Parts; + } + + pub trait Pin { + fn sleep_mode(&mut self, on: bool) -> &mut Self; + + fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self; + + fn listen(&mut self, event: Event) { + self.listen_with_options(event, true, false, false) + } + + fn listen_with_options( + &mut self, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, + ); + + fn unlisten(&mut self); + + fn clear_interrupt(&mut self); + + fn is_pcore_interrupt_set(&mut self) -> bool; + + fn is_pcore_non_maskable_interrupt_set(&mut self) -> bool; + + fn is_acore_interrupt_set(&mut self) -> bool; + + fn is_acore_non_maskable_interrupt_set(&mut self) -> bool; + + fn enable_hold(&mut self, on: bool); + } + + pub trait InputPin: Pin { + fn set_to_input(&mut self) -> &mut Self; + + fn enable_input(&mut self, on: bool) -> &mut Self; + + fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self; + + fn is_input_high(&mut self) -> bool; + + fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { + self.connect_input_to_peripheral_with_options(signal, false, false) + } + + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + ) -> &mut Self; + } + + pub trait OutputPin: Pin { + fn set_to_open_drain_output(&mut self) -> &mut Self; + + fn set_to_push_pull_output(&mut self) -> &mut Self; + + fn enable_output(&mut self, on: bool) -> &mut Self; + + fn set_output_high(&mut self, on: bool) -> &mut Self; + + fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self; + + fn enable_open_drain(&mut self, on: bool) -> &mut Self; + + fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self; + + fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self; + + fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self; + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { + self.connect_peripheral_to_output_with_options(signal, false, false, false, false) + } + + fn connect_peripheral_to_output_with_options( + &mut self, + signal: OutputSignal, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + force_via_gpio_mux: bool, + ) -> &mut Self; + + fn internal_pull_up(&mut self, on: bool) -> &mut Self; + + fn internal_pull_down(&mut self, on: bool) -> &mut Self; + } + + pub trait RTCPin {} + + pub trait AnalogPin {} + + #[derive(Copy, Clone)] + pub enum Event { + RisingEdge = 1, + FallingEdge = 2, + AnyEdge = 3, + LowLevel = 4, + HighLevel = 5, + } + + pub struct Unknown {} + + pub struct Input { + _mode: PhantomData, + } + + pub struct RTCInput { + _mode: PhantomData, + } + + pub struct Floating; + + pub struct PullDown; + + pub struct PullUp; + + pub struct Output { + _mode: PhantomData, + } + + pub struct RTCOutput { + _mode: PhantomData, + } + + pub struct OpenDrain; + + pub struct PushPull; + + pub struct Analog; + + pub struct Alternate { + _mode: PhantomData, + } + + pub struct AF0; + + pub struct AF1; + + pub struct AF2; + + pub enum DriveStrength { + I5mA = 0, + I10mA = 1, + I20mA = 2, + I40mA = 3, + } + + #[derive(PartialEq)] + pub enum AlternateFunction { + Function0 = 0, + Function1 = 1, + Function2 = 2, + Function3 = 3, + Function4 = 4, + Function5 = 5, + } + + pub fn connect_low_to_peripheral(signal: InputSignal) { + unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(false) + .in_sel() + .bits(0x1f) + }); + } + + pub fn connect_high_to_peripheral(signal: InputSignal) { + unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(false) + .in_sel() + .bits(0x1e) + }); + } + + impl GpioExt for GPIO { + type Parts = Pins; + + fn split(self) -> Self::Parts { + Pins { + $( + $pname: $pxi { _mode: PhantomData }, + )+ + } + } + } + + + pub struct Pins { + $( + + pub $pname: $pxi, + )+ + } + + + + $( + + pub struct $pxi { + _mode: PhantomData, + } + + impl_pin_wrap!($gpio_function, $pxi, $pin_num, $iomux_reg, $type, $bank, $cores + $( ,( $( $af_input_signal: $af_input ),* ) )? ); + impl_output_wrap!($gpio_function, $pxi, $pin_num, $iomux_reg, $type, $bank + $($( ,( $( $af_output_signal: $af_output ),* ) )? )? ); + )+ + }; +} + +pub use gpio; +pub use impl_input; +pub use impl_output; +pub use impl_output_wrap; +pub use impl_pin_wrap; diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 97dc737e42f..12718b11b72 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -9,9 +9,11 @@ pub use esp32s2_pac as pac; #[cfg(feature = "esp32s3")] pub use esp32s3_pac as pac; +pub mod gpio; pub mod prelude; pub mod serial; pub mod timer; +pub use gpio::*; pub use serial::Serial; pub use timer::Timer; diff --git a/esp-hal-common/src/serial.rs b/esp-hal-common/src/serial.rs index 6591ed1b959..6d727c5547a 100644 --- a/esp-hal-common/src/serial.rs +++ b/esp-hal-common/src/serial.rs @@ -112,13 +112,6 @@ impl Write for Serial { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { if self.uart.get_tx_fifo_count() < UART_FIFO_SIZE { - #[cfg(feature = "esp32")] - self.uart - .register_block() - .fifo() - .write(|w| unsafe { w.rxfifo_rd_byte().bits(word) }); - - #[cfg(not(feature = "esp32"))] self.uart .register_block() .fifo @@ -144,16 +137,6 @@ impl Read for Serial { fn read(&mut self) -> nb::Result { if self.uart.get_rx_fifo_count() > 0 { - #[cfg(feature = "esp32")] - let value = self - .uart - .register_block() - .fifo() - .read() - .rxfifo_rd_byte() - .bits(); - - #[cfg(not(feature = "esp32"))] let value = self .uart .register_block() diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index 1a6c4ebb425..f71cd7bbdb4 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -99,13 +99,17 @@ pub trait Instance { reg_block .wdtwprotect - .write(|w| unsafe { w.wdt_wkey().bits(0u32) }); + .write(|w| unsafe { w.wdt_wkey().bits(0x50D8_3AA1u32) }); - reg_block.wdtconfig0.write(|w| w.wdt_en().bit(enabled)); + if !enabled { + reg_block.wdtconfig0.write(|w| unsafe { w.bits(0) }); + } else { + reg_block.wdtconfig0.write(|w| w.wdt_en().bit(true)); + } reg_block .wdtwprotect - .write(|w| unsafe { w.wdt_wkey().bits(0x50D8_3AA1u32) }); + .write(|w| unsafe { w.wdt_wkey().bits(0u32) }); } } diff --git a/esp32-hal/examples/blinky.rs b/esp32-hal/examples/blinky.rs new file mode 100644 index 00000000000..d12d92f72c0 --- /dev/null +++ b/esp32-hal/examples/blinky.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] + +use esp32_hal::{gpio::IO, pac, prelude::*, Timer}; +use nb::block; +use panic_halt as _; +use xtensa_lx_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = pac::Peripherals::take().unwrap(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut timer0 = Timer::new(peripherals.TIMG0); + + timer0.disable(); + + let mut led = io.pins.gpio15.into_push_pull_output(); + led.set_high().unwrap(); + + timer0.start(10_000_000u64); + + loop { + led.toggle().unwrap(); + block!(timer0.wait()).unwrap(); + } +} diff --git a/esp32-hal/src/gpio.rs b/esp32-hal/src/gpio.rs new file mode 100644 index 00000000000..d845306cdf3 --- /dev/null +++ b/esp32-hal/src/gpio.rs @@ -0,0 +1,543 @@ +use esp_hal_common::gpio::gpio; + +use crate::hal_gpio::*; + +type OutputSignalType = u16; +const OUTPUT_SIGNAL_MAX: u16 = 548; +const INPUT_SIGNAL_MAX: u16 = 539; + +/// Peripheral input signals for the GPIO mux +#[allow(non_camel_case_types)] +#[derive(PartialEq, Copy, Clone)] +pub enum InputSignal { + SPICLK = 0, + SPIQ = 1, + SPID = 2, + SPIHD = 3, + SPIWP = 4, + SPICS0 = 5, + SPICS1 = 6, + SPICS2 = 7, + HSPICLK = 8, + HSPIQ = 9, + HSPID = 10, + HSPICS0 = 11, + HSPIHD = 12, + HSPIWP = 13, + U0RXD = 14, + U0CTS = 15, + U0DSR = 16, + U1RXD = 17, + U1CTS = 18, + I2CM_SDA = 20, + EXT_I2C_SDA = 22, + I2S0O_BCK = 23, + I2S1O_BCK = 24, + I2S0O_WS = 25, + I2S1O_WS = 26, + I2S0I_BCK = 27, + I2S0I_WS = 28, + I2CEXT0_SCL = 29, + I2CEXT0_SDA = 30, + PWM0_SYNC0 = 31, + PWM0_SYNC1 = 32, + PWM0_SYNC2 = 33, + PWM0_F0 = 34, + PWM0_F1 = 35, + PWM0_F2 = 36, + GPIO_BT_ACTIVE = 37, + GPIO_BT_PRIORITY = 38, + PCNT_SIG_CH0_0 = 39, + PCNT_SIG_CH1_0 = 40, + PCNT_CTRL_CH0_0 = 41, + PCNT_CTRL_CH1_0 = 42, + PCNT_SIG_CH0_1 = 43, + PCNT_SIG_CH1_1 = 44, + PCNT_CTRL_CH0_1 = 45, + PCNT_CTRL_CH1_1 = 46, + PCNT_SIG_CH0_2 = 47, + PCNT_SIG_CH1_2 = 48, + PCNT_CTRL_CH0_2 = 49, + PCNT_CTRL_CH1_2 = 50, + PCNT_SIG_CH0_3 = 51, + PCNT_SIG_CH1_3 = 52, + PCNT_CTRL_CH0_3 = 53, + PCNT_CTRL_CH1_3 = 54, + PCNT_SIG_CH0_4 = 55, + PCNT_SIG_CH1_4 = 56, + PCNT_CTRL_CH0_4 = 57, + PCNT_CTRL_CH1_4 = 58, + HSPICS1 = 61, + HSPICS2 = 62, + VSPICLK = 63, + VSPIQ = 64, + VSPID = 65, + VSPIHD = 66, + VSPIWP = 67, + VSPICS0 = 68, + VSPICS1 = 69, + VSPICS2 = 70, + PCNT_SIG_CH0_5 = 71, + PCNT_SIG_CH1_5 = 72, + PCNT_CTRL_CH0_5 = 73, + PCNT_CTRL_CH1_5 = 74, + PCNT_SIG_CH0_6 = 75, + PCNT_SIG_CH1_6 = 76, + PCNT_CTRL_CH0_6 = 77, + PCNT_CTRL_CH1_6 = 78, + PCNT_SIG_CH0_7 = 79, + PCNT_SIG_CH1_7 = 80, + PCNT_CTRL_CH0_7 = 81, + PCNT_CTRL_CH1_7 = 82, + RMT_SIG_0 = 83, + RMT_SIG_1 = 84, + RMT_SIG_2 = 85, + RMT_SIG_3 = 86, + RMT_SIG_4 = 87, + RMT_SIG_5 = 88, + RMT_SIG_6 = 89, + RMT_SIG_7 = 90, + EXT_ADC_START = 93, + CAN_RX = 94, + I2CEXT1_SCL = 95, + I2CEXT1_SDA = 96, + HOST_CARD_DETECT_N_1 = 97, + HOST_CARD_DETECT_N_2 = 98, + HOST_CARD_WRITE_PRT_1 = 99, + HOST_CARD_WRITE_PRT_2 = 100, + HOST_CARD_INT_N_1 = 101, + HOST_CARD_INT_N_2 = 102, + PWM1_SYNC0 = 103, + PWM1_SYNC1 = 104, + PWM1_SYNC2 = 105, + PWM1_F0 = 106, + PWM1_F1 = 107, + PWM1_F2 = 108, + PWM0_CAP0 = 109, + PWM0_CAP1 = 110, + PWM0_CAP2 = 111, + PWM1_CAP0 = 112, + PWM1_CAP1 = 113, + PWM1_CAP2 = 114, + PWM2_FLTA = 115, + PWM2_FLTB = 116, + PWM2_CAP1 = 117, + PWM2_CAP2 = 118, + PWM2_CAP3 = 119, + PWM3_FLTA = 120, + PWM3_FLTB = 121, + PWM3_CAP1 = 122, + PWM3_CAP2 = 123, + PWM3_CAP3 = 124, + CAN_CLKOUT = 125, + SPID4 = 128, + SPID5 = 129, + SPID6 = 130, + SPID7 = 131, + HSPID4 = 132, + HSPID5 = 133, + HSPID6 = 134, + HSPID7 = 135, + VSPID4 = 136, + VSPID5 = 137, + VSPID6 = 138, + VSPID7 = 139, + I2S0I_DATA_0 = 140, + I2S0I_DATA_1 = 141, + I2S0I_DATA_2 = 142, + I2S0I_DATA_3 = 143, + I2S0I_DATA_4 = 144, + I2S0I_DATA_5 = 145, + I2S0I_DATA_6 = 146, + I2S0I_DATA_7 = 147, + I2S0I_DATA_8 = 148, + I2S0I_DATA_9 = 149, + I2S0I_DATA_10 = 150, + I2S0I_DATA_11 = 151, + I2S0I_DATA_12 = 152, + I2S0I_DATA_13 = 153, + I2S0I_DATA_14 = 154, + I2S0I_DATA_15 = 155, + I2S1I_BCK = 164, + I2S1I_WS = 165, + I2S1I_DATA_0 = 166, + I2S1I_DATA_1 = 167, + I2S1I_DATA_2 = 168, + I2S1I_DATA_3 = 169, + I2S1I_DATA_4 = 170, + I2S1I_DATA_5 = 171, + I2S1I_DATA_6 = 172, + I2S1I_DATA_7 = 173, + I2S1I_DATA_8 = 174, + I2S1I_DATA_9 = 175, + I2S1I_DATA_10 = 176, + I2S1I_DATA_11 = 177, + I2S1I_DATA_12 = 178, + I2S1I_DATA_13 = 179, + I2S1I_DATA_14 = 180, + I2S1I_DATA_15 = 181, + I2S0I_H_SYNC = 190, + I2S0I_V_SYNC = 191, + I2S0I_H_ENABLE = 192, + I2S1I_H_SYNC = 193, + I2S1I_V_SYNC = 194, + I2S1I_H_ENABLE = 195, + U2RXD = 198, + U2CTS = 199, + EMAC_MDC = 200, + EMAC_MDI = 201, + EMAC_CRS = 202, + EMAC_COL = 203, + PCMFSYNC = 204, + PCMCLK = 205, + PCMDIN = 206, + SIG_IN_FUNC224 = 224, + SIG_IN_FUNC225 = 225, + SIG_IN_FUNC226 = 226, + SIG_IN_FUNC227 = 227, + SIG_IN_FUNC228 = 228, + + SD_DATA0 = 512, + SD_DATA1, + SD_DATA2, + SD_DATA3, + HS1_DATA0, + HS1_DATA1, + HS1_DATA2, + HS1_DATA3, + HS1_DATA4, + HS1_DATA5, + HS1_DATA6, + HS1_DATA7, + HS2_DATA0, + HS2_DATA1, + HS2_DATA2, + HS2_DATA3, + + EMAC_TX_CLK, + EMAC_RXD2, + EMAC_TX_ER, + EMAC_RX_CLK, + EMAC_RX_ER, + EMAC_RXD3, + EMAC_RXD0, + EMAC_RXD1, + EMAC_RX_DV, + + MTDI, + MTCK, + MTMS, +} + +/// Peripheral output signals for the GPIO mux +#[allow(non_camel_case_types)] +#[derive(PartialEq, Copy, Clone)] +pub enum OutputSignal { + SPICLK = 0, + SPIQ = 1, + SPID = 2, + SPIHD = 3, + SPIWP = 4, + SPICS0 = 5, + SPICS1 = 6, + SPICS2 = 7, + HSPICLK = 8, + HSPIQ = 9, + HSPID = 10, + HSPICS0 = 11, + HSPIHD = 12, + HSPIWP = 13, + U0TXD = 14, + U0RTS = 15, + U0DTR = 16, + U1TXD = 17, + U1RTS = 18, + I2CM_SCL = 19, + I2CM_SDA = 20, + EXT2C_SCL = 21, + EXT2C_SDA = 22, + I2S0O_BCK = 23, + I2S1O_BCK = 24, + I2S0O_WS = 25, + I2S1O_WS = 26, + I2S0I_BCK = 27, + I2S0I_WS = 28, + I2CEXT0_SCL = 29, + I2CEXT0_SDA = 30, + SDIO_TOHOSTT = 31, + PWM0_0A = 32, + PWM0_0B = 33, + PWM0_1A = 34, + PWM0_1B = 35, + PWM0_2A = 36, + PWM0_2B = 37, + GPIO_WLAN_ACTIVE = 40, + BB_DIAG0 = 41, + BB_DIAG1 = 42, + BB_DIAG2 = 43, + BB_DIAG3 = 44, + BB_DIAG4 = 45, + BB_DIAG5 = 46, + BB_DIAG6 = 47, + BB_DIAG7 = 48, + BB_DIAG8 = 49, + BB_DIAG9 = 50, + BB_DIAG10 = 51, + BB_DIAG11 = 52, + BB_DIAG12 = 53, + BB_DIAG13 = 54, + BB_DIAG14 = 55, + BB_DIAG15 = 56, + BB_DIAG16 = 57, + BB_DIAG17 = 58, + BB_DIAG18 = 59, + BB_DIAG19 = 60, + HSPICS1 = 61, + HSPICS2 = 62, + VSPICLK = 63, + VSPIQ = 64, + VSPID = 65, + VSPIHD = 66, + VSPIWP = 67, + VSPICS0 = 68, + VSPICS1 = 69, + VSPICS2 = 70, + LEDC_HS_SIG_0 = 71, + LEDC_HS_SIG_1 = 72, + LEDC_HS_SIG_2 = 73, + LEDC_HS_SIG_3 = 74, + LEDC_HS_SIG_4 = 75, + LEDC_HS_SIG_5 = 76, + LEDC_HS_SIG_6 = 77, + LEDC_HS_SIG_7 = 78, + LEDC_LS_SIG_0 = 79, + LEDC_LS_SIG_1 = 80, + LEDC_LS_SIG_2 = 81, + LEDC_LS_SIG_3 = 82, + LEDC_LS_SIG_4 = 83, + LEDC_LS_SIG_5 = 84, + LEDC_LS_SIG_6 = 85, + LEDC_LS_SIG_7 = 86, + RMT_SIG_0 = 87, + RMT_SIG_1 = 88, + RMT_SIG_2 = 89, + RMT_SIG_3 = 90, + RMT_SIG_4 = 91, + RMT_SIG_5 = 92, + RMT_SIG_6 = 93, + RMT_SIG_7 = 94, + I2CEXT1_SCL = 95, + I2CEXT1_SDA = 96, + HOST_CCMD_OD_PULLUP_EN_N = 97, + HOST_RST_N_1 = 98, + HOST_RST_N_2 = 99, + GPIO_SD0 = 100, + GPIO_SD1 = 101, + GPIO_SD2 = 102, + GPIO_SD3 = 103, + GPIO_SD4 = 104, + GPIO_SD5 = 105, + GPIO_SD6 = 106, + GPIO_SD7 = 107, + PWM1_0A = 108, + PWM1_0B = 109, + PWM1_1A = 110, + PWM1_1B = 111, + PWM1_2A = 112, + PWM1_2B = 113, + PWM2_1H = 114, + PWM2_1L = 115, + PWM2_2H = 116, + PWM2_2L = 117, + PWM2_3H = 118, + PWM2_3L = 119, + PWM2_4H = 120, + PWM2_4L = 121, + CAN_TX = 123, + CAN_BUS_OFF_ON = 124, + SPID4 = 128, + SPID5 = 129, + SPID6 = 130, + SPID7 = 131, + HSPID4 = 132, + HSPID5 = 133, + HSPID6 = 134, + HSPID7 = 135, + VSPID4 = 136, + VSPID5 = 137, + VSPID6 = 138, + VSPID7 = 139, + I2S0O_DATA_0 = 140, + I2S0O_DATA_1 = 141, + I2S0O_DATA_2 = 142, + I2S0O_DATA_3 = 143, + I2S0O_DATA_4 = 144, + I2S0O_DATA_5 = 145, + I2S0O_DATA_6 = 146, + I2S0O_DATA_7 = 147, + I2S0O_DATA_8 = 148, + I2S0O_DATA_9 = 149, + I2S0O_DATA_10 = 150, + I2S0O_DATA_11 = 151, + I2S0O_DATA_12 = 152, + I2S0O_DATA_13 = 153, + I2S0O_DATA_14 = 154, + I2S0O_DATA_15 = 155, + I2S0O_DATA_16 = 156, + I2S0O_DATA_17 = 157, + I2S0O_DATA_18 = 158, + I2S0O_DATA_19 = 159, + I2S0O_DATA_20 = 160, + I2S0O_DATA_21 = 161, + I2S0O_DATA_22 = 162, + I2S0O_DATA_23 = 163, + I2S1I_BCK = 164, + I2S1I_WS = 165, + I2S1O_DATA_0 = 166, + I2S1O_DATA_1 = 167, + I2S1O_DATA_2 = 168, + I2S1O_DATA_3 = 169, + I2S1O_DATA_4 = 170, + I2S1O_DATA_5 = 171, + I2S1O_DATA_6 = 172, + I2S1O_DATA_7 = 173, + I2S1O_DATA_8 = 174, + I2S1O_DATA_9 = 175, + I2S1O_DATA_10 = 176, + I2S1O_DATA_11 = 177, + I2S1O_DATA_12 = 178, + I2S1O_DATA_13 = 179, + I2S1O_DATA_14 = 180, + I2S1O_DATA_15 = 181, + I2S1O_DATA_16 = 182, + I2S1O_DATA_17 = 183, + I2S1O_DATA_18 = 184, + I2S1O_DATA_19 = 185, + I2S1O_DATA_20 = 186, + I2S1O_DATA_21 = 187, + I2S1O_DATA_22 = 188, + I2S1O_DATA_23 = 189, + PWM3_1H = 190, + PWM3_1L = 191, + PWM3_2H = 192, + PWM3_2L = 193, + PWM3_3H = 194, + PWM3_3L = 195, + PWM3_4H = 196, + PWM3_4L = 197, + U2TXD = 198, + U2RTS = 199, + EMAC_MDC = 200, + EMAC_MDO = 201, + EMAC_CRS = 202, + EMAC_COL = 203, + BT_AUDIO0RQ = 204, + BT_AUDIO1RQ = 205, + BT_AUDIO2RQ = 206, + BLE_AUDIO0RQ = 207, + BLE_AUDIO1RQ = 208, + BLE_AUDIO2RQ = 209, + PCMFSYNC = 210, + PCMCLK = 211, + PCMDOUT = 212, + BLE_AUDIO_SYNC0_P = 213, + BLE_AUDIO_SYNC1_P = 214, + BLE_AUDIO_SYNC2_P = 215, + ANT_SEL0 = 216, + ANT_SEL1 = 217, + ANT_SEL2 = 218, + ANT_SEL3 = 219, + ANT_SEL4 = 220, + ANT_SEL5 = 221, + ANT_SEL6 = 222, + ANT_SEL7 = 223, + SIGNAL_224 = 224, + SIGNAL_225 = 225, + SIGNAL_226 = 226, + SIGNAL_227 = 227, + SIGNAL_228 = 228, + GPIO = 256, + + CLK_OUT1 = 512, + CLK_OUT2, + CLK_OUT3, + SD_CLK, + SD_CMD, + SD_DATA0, + SD_DATA1, + SD_DATA2, + SD_DATA3, + HS1_CLK, + HS1_CMD, + HS1_DATA0, + HS1_DATA1, + HS1_DATA2, + HS1_DATA3, + HS1_DATA4, + HS1_DATA5, + HS1_DATA6, + HS1_DATA7, + HS1_STROBE, + HS2_CLK, + HS2_CMD, + HS2_DATA0, + HS2_DATA1, + HS2_DATA2, + HS2_DATA3, + + EMAC_TX_CLK, + EMAC_TX_ER, + EMAC_TXD3, + EMAC_RX_ER, + EMAC_TXD2, + EMAC_CLK_OUT, + EMAC_CLK_180, + EMAC_TXD0, + EMAC_TX_EN, + EMAC_TXD1, + + MTDO, +} + +gpio! { + Function2, + DualCore, + Gpio0: (gpio0, 0, gpio0, IO, RTC, Bank0), (EMAC_TX_CLK: Function5), (CLK_OUT1: Function1), + Gpio1: (gpio1, 1, gpio1, IO, 0, Bank0), (EMAC_RXD2: Function5), (U0TXD: Function1, CLK_OUT3: Function1), + Gpio2: (gpio2, 2, gpio2, IO, RTC, Bank0), (HSPIWP: Function1, HS2_DATA0: Function3, SD_DATA0: Function4), (HS2_DATA0: Function3, SD_DATA0: Function4), + Gpio3: (gpio3, 3, gpio3, IO, 0, Bank0), (U0RXD: Function0), (CLK_OUT2: Function1), + Gpio4: (gpio4, 4, gpio4, IO, RTC, Bank0), (HSPIHD: Function1, HS2_DATA1: Function3, SD_DATA1: Function4, EMAC_TX_ER: Function5), (HS2_DATA1: Function3, SD_DATA1: Function4), + Gpio5: (gpio5, 5, gpio5, IO, 0, Bank0), (VSPICS0: Function1, HS1_DATA6: Function3, EMAC_RX_CLK: Function5), (HS1_DATA6: Function3), + Gpio6: (gpio6, 6, gpio6, IO, 0, Bank0), (U1CTS: Function4), (SD_CLK: Function0, SPICLK: Function1, HS1_CLK: Function3), + Gpio7: (gpio7, 7, gpio7, IO, 0, Bank0), (SD_DATA0: Function0, SPIQ: Function1, HS1_DATA0: Function3), (SD_DATA0: Function0, SPIQ: Function1, HS1_DATA0: Function3, U2RTS: Function4), + Gpio8: (gpio8, 8, gpio8, IO, 0, Bank0), (SD_DATA1: Function0, SPID: Function1, HS1_DATA1: Function3, U2CTS: Function4), (SD_DATA1: Function0, SPID: Function1, HS1_DATA1: Function3), + Gpio9: (gpio9, 9, gpio9, IO, 0, Bank0), (SD_DATA2: Function0, SPIHD: Function1, HS1_DATA2: Function3, U1RXD: Function4), (SD_DATA2: Function0, SPIHD: Function1, HS1_DATA2: Function3), + Gpio10: (gpio10, 10, gpio10, IO, 0, Bank0), (SD_DATA3: Function0, SPIWP: Function1, HS1_DATA3: Function3), (SD_DATA3: Function0, SPIWP: Function1, HS1_DATA3: Function3, U1TXD: Function4), + Gpio11: (gpio11, 11, gpio11, IO, 0, Bank0), (SPICS0: Function1), (SD_CMD: Function0, SPICS0: Function1, HS1_CMD: Function3, U1RTS: Function4), + Gpio12: (gpio12, 12, gpio12, IO, RTC, Bank0), (MTDI: Function0, HSPIQ: Function1, HS2_DATA2: Function3, SD_DATA2: Function4), (HSPIQ: Function1, HS2_DATA2: Function3, SD_DATA2: Function4, EMAC_TXD3: Function5), + Gpio13: (gpio13, 13, gpio13, IO, RTC, Bank0), (MTCK: Function0, HSPID: Function1, HS2_DATA3: Function3, SD_DATA3: Function4), (HSPID: Function1, HS2_DATA3: Function3, SD_DATA3: Function4, EMAC_RX_ER: Function5), + Gpio14: (gpio14, 14, gpio14, IO, RTC, Bank0), (MTMS: Function0, HSPICLK: Function1), (HSPICLK: Function1, HS2_CLK: Function3, SD_CLK: Function4, EMAC_TXD2: Function5), + Gpio15: (gpio15, 15, gpio15, IO, RTC, Bank0), (HSPICS0: Function1, EMAC_RXD3: Function5), (MTDO: Function0, HSPICS0: Function1, HS2_CMD: Function3, SD_CMD: Function4), + Gpio16: (gpio16, 16, gpio16, IO, 0, Bank0), (HS1_DATA4: Function3, U2RXD: Function4), (HS1_DATA4: Function3, EMAC_CLK_OUT: Function5), + Gpio17: (gpio17, 17, gpio17, IO, 0, Bank0), (HS1_DATA5: Function3), (HS1_DATA5: Function3, U2TXD: Function4, EMAC_CLK_180: Function5), + Gpio18: (gpio18, 18, gpio18, IO, 0, Bank0), (VSPICLK: Function1, HS1_DATA7: Function3), (VSPICLK: Function1, HS1_DATA7: Function3), + Gpio19: (gpio19, 19, gpio19, IO, 0, Bank0), (VSPIQ: Function1, U0CTS: Function3), (VSPIQ: Function1, EMAC_TXD0: Function5), + Gpio20: (gpio20, 20, gpio20, IO, 0, Bank0), + Gpio21: (gpio21, 21, gpio21, IO, 0, Bank0), (VSPIHD: Function1), (VSPIHD: Function1, EMAC_TX_EN: Function5), + + Gpio22: (gpio22, 22, gpio22, IO, 0, Bank0), (VSPIWP: Function1), (VSPIWP: Function1, U0RTS: Function3, EMAC_TXD1: Function5), + Gpio23: (gpio23, 23, gpio23, IO, 0, Bank0), (VSPID: Function1), (VSPID: Function1, HS1_STROBE: Function3), + Gpio24: (gpio24, 24, gpio24, IO, 0, Bank0), + Gpio25: (gpio25, 25, gpio25, IO, 0, Bank0), (EMAC_RXD0: Function5), (), + Gpio26: (gpio26, 26, gpio26, IO, 0, Bank0), (EMAC_RXD1: Function5), (), + Gpio27: (gpio27, 27, gpio27, IO, 0, Bank0), (EMAC_RX_DV: Function5), (), + + Gpio32: (gpio32, 32, gpio32, IO, 0, Bank1), + Gpio33: (gpio33, 33, gpio33, IO, 0, Bank1), + Gpio34: (gpio34, 34, gpio34, Input, 0, Bank1), + Gpio35: (gpio35, 35, gpio35, Input, 0, Bank1), + Gpio36: (gpio36, 36, gpio36, Input, 0, Bank1), + Gpio37: (gpio37, 37, gpio37, Input, 0, Bank1), + Gpio38: (gpio38, 38, gpio38, Input, 0, Bank1), + Gpio39: (gpio39, 39, gpio39, Input, 0, Bank1), +} diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index dc1a69c3b53..5acbee4f9a7 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -1,7 +1,9 @@ #![no_std] pub use embedded_hal as ehal; -pub use esp_hal_common::{pac, prelude, Serial, Timer}; +pub use esp_hal_common::{gpio as hal_gpio, pac, prelude, Serial, Timer}; + +pub mod gpio; #[no_mangle] extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index 8192ebc6ea9..e9dd53bd193 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -25,3 +25,6 @@ panic-halt = "0.2" [features] default = ["rt"] rt = ["riscv-rt"] + +[package.metadata.espflash] +format = "direct-boot" diff --git a/esp32c3-hal/build.rs b/esp32c3-hal/build.rs index f455dd6343b..042a451981f 100644 --- a/esp32c3-hal/build.rs +++ b/esp32c3-hal/build.rs @@ -14,6 +14,11 @@ fn main() { .write_all(include_bytes!("esp32c3-link.x")) .unwrap(); + File::create(out.join("riscv-link.x")) + .unwrap() + .write_all(include_bytes!("riscv-link.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); // Only re-run the build script when memory.x is changed, diff --git a/esp32c3-hal/esp32c3-link.x b/esp32c3-hal/esp32c3-link.x index a4906e32634..63ba963a232 100644 --- a/esp32c3-hal/esp32c3-link.x +++ b/esp32c3-hal/esp32c3-link.x @@ -1,2 +1,14 @@ INCLUDE memory.x -INCLUDE link.x + +SECTIONS +{ + .header : AT(0) + { + LONG(0xaedb041d) + LONG(0xaedb041d) + } > IROM +} + +_stext = ORIGIN(IROM) + 8; + +INCLUDE riscv-link.x diff --git a/esp32c3-hal/esp32c3-memory.x b/esp32c3-hal/esp32c3-memory.x index 5e29c5bb3d9..8aece714c8c 100644 --- a/esp32c3-hal/esp32c3-memory.x +++ b/esp32c3-hal/esp32c3-memory.x @@ -1,15 +1,39 @@ MEMORY { + /* + https://github.com/espressif/esptool/blob/master/esptool.py#L1919 + MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], + [0x3C000000, 0x3C800000, "DROM"], + [0x3FC80000, 0x3FCE0000, "DRAM"], + [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], + [0x3FF00000, 0x3FF20000, "DROM_MASK"], + [0x40000000, 0x40060000, "IROM_MASK"], + [0x42000000, 0x42800000, "IROM"], + [0x4037C000, 0x403E0000, "IRAM"], + [0x50000000, 0x50002000, "RTC_IRAM"], + [0x50000000, 0x50002000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"]] + */ /* 400K of on soc RAM, 16K reserved for cache */ - ICACHE : ORIGIN = 0x4037C000, LENGTH = 0x4000 - IRAM : ORIGIN = 0x4037C000 + 0x4000, LENGTH = 400K - 0x4000 - /* 384K of on soc ROM */ - IROM : ORIGIN = 0x42000020, LENGTH = 0x60000 + ICACHE : ORIGIN = 0x4037C000, LENGTH = 0x4000 + /* Instruction RAM */ + IRAM : ORIGIN = 0x4037C000 + 0x4000, LENGTH = 400K - 0x4000 + /* Data RAM */ + DRAM : ORIGIN = 0x3FC80000, LENGTH = 0x50000 + + + /* External flash */ + /* Instruction ROM */ + IROM : ORIGIN = 0x42000000, LENGTH = 0x400000 + /* Data ROM */ + DROM : ORIGIN = 0x3C000000, LENGTH = 0x400000 } -REGION_ALIAS("REGION_TEXT", IRAM); -REGION_ALIAS("REGION_RODATA", IRAM); -REGION_ALIAS("REGION_DATA", IRAM); -REGION_ALIAS("REGION_BSS", IRAM); -REGION_ALIAS("REGION_HEAP", IRAM); -REGION_ALIAS("REGION_STACK", IRAM); + +REGION_ALIAS("REGION_TEXT", IROM); +REGION_ALIAS("REGION_RODATA", DROM); + +REGION_ALIAS("REGION_DATA", DRAM); +REGION_ALIAS("REGION_BSS", DRAM); +REGION_ALIAS("REGION_HEAP", DRAM); +REGION_ALIAS("REGION_STACK", DRAM); \ No newline at end of file diff --git a/esp32c3-hal/examples/blinky.rs b/esp32c3-hal/examples/blinky.rs index 66da1b5bc68..4bf84249750 100644 --- a/esp32c3-hal/examples/blinky.rs +++ b/esp32c3-hal/examples/blinky.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] -use esp32c3_hal::{pac, prelude::*, RtcCntl, Timer, IO}; +use esp32c3_hal::{gpio::IO, pac, prelude::*, RtcCntl, Timer}; use nb::block; use panic_halt as _; use riscv_rt::entry; @@ -13,12 +13,14 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); let mut timer0 = Timer::new(peripherals.TIMG0); + let mut timer1 = Timer::new(peripherals.TIMG1); rtc_cntl.set_super_wdt_enable(false); rtc_cntl.set_wdt_enable(false); timer0.disable(); + timer1.disable(); - let mut led = io.pins.gpio2.into_push_pull_output(); + let mut led = io.pins.gpio5.into_push_pull_output(); led.set_high().unwrap(); timer0.start(10_000_000u64); diff --git a/esp32c3-hal/riscv-link.x b/esp32c3-hal/riscv-link.x new file mode 100644 index 00000000000..763baa91e53 --- /dev/null +++ b/esp32c3-hal/riscv-link.x @@ -0,0 +1,173 @@ +PROVIDE(_stext = ORIGIN(REGION_TEXT)); +PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK)); +PROVIDE(_max_hart_id = 0); +PROVIDE(_hart_stack_size = 2K); +PROVIDE(_heap_size = 0); + +PROVIDE(UserSoft = DefaultHandler); +PROVIDE(SupervisorSoft = DefaultHandler); +PROVIDE(MachineSoft = DefaultHandler); +PROVIDE(UserTimer = DefaultHandler); +PROVIDE(SupervisorTimer = DefaultHandler); +PROVIDE(MachineTimer = DefaultHandler); +PROVIDE(UserExternal = DefaultHandler); +PROVIDE(SupervisorExternal = DefaultHandler); +PROVIDE(MachineExternal = DefaultHandler); + +PROVIDE(DefaultHandler = DefaultInterruptHandler); +PROVIDE(ExceptionHandler = DefaultExceptionHandler); + +/* # Pre-initialization function */ +/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function, + then the function this points to will be called before the RAM is initialized. */ +PROVIDE(__pre_init = default_pre_init); + +/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */ +PROVIDE(_setup_interrupts = default_setup_interrupts); + +/* # Multi-processing hook function + fn _mp_hook() -> bool; + + This function is called from all the harts and must return true only for one hart, + which will perform memory initialization. For other harts it must return false + and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt). +*/ +PROVIDE(_mp_hook = default_mp_hook); + +SECTIONS +{ + .text.dummy (NOLOAD) : + { + /* This section is intended to make _stext address work */ + . = ABSOLUTE(_stext); + } > REGION_TEXT + + .text _stext : + { + /* Put reset handler first in .text section so it ends up as the entry */ + /* point of the program. */ + KEEP(*(.init)); + KEEP(*(.init.rust)); + . = ALIGN(4); + (*(.trap)); + (*(.trap.rust)); + + *(.text .text.*); + _etext = .; + } > REGION_TEXT + + _text_size = _etext - _stext + 8; + .rodata ORIGIN(DROM) + _text_size : AT(_text_size) + { + _srodata = .; + *(.srodata .srodata.*); + *(.rodata .rodata.*); + + /* 4-byte align the end (VMA) of this section. + This is required by LLD to ensure the LMA of the following .data + section will have the correct alignment. */ + . = ALIGN(4); + _erodata = .; + } > REGION_RODATA + + _rodata_size = _erodata - _srodata + 8; + .data ORIGIN(DRAM) : AT(_text_size + _rodata_size) + { + _sidata = LOADADDR(.data); + _sdata = .; + /* Must be called __global_pointer$ for linker relaxations to work. */ + PROVIDE(__global_pointer$ = . + 0x800); + *(.sdata .sdata.* .sdata2 .sdata2.*); + *(.data .data.*); + . = ALIGN(4); + _edata = .; + } > REGION_DATA + + .bss (NOLOAD) : + { + _sbss = .; + *(.sbss .sbss.* .bss .bss.*); + . = ALIGN(4); + _ebss = .; + } > REGION_BSS + + /* fictitious region that represents the memory available for the heap */ + .heap (NOLOAD) : + { + _sheap = .; + . += _heap_size; + . = ALIGN(4); + _eheap = .; + } > REGION_HEAP + + /* fictitious region that represents the memory available for the stack */ + .stack (NOLOAD) : + { + _estack = .; + . = ABSOLUTE(_stack_start); + _sstack = .; + } > REGION_STACK + + /* fake output .got section */ + /* Dynamic relocations are unsupported. This section is only used to detect + relocatable code in the input files and raise an error if relocatable code + is found */ + .got (INFO) : + { + KEEP(*(.got .got.*)); + } + + .eh_frame (INFO) : { KEEP(*(.eh_frame)) } + .eh_frame_hdr (INFO) : { *(.eh_frame_hdr) } +} + +/* Do not exceed this mark in the error messages above | */ +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_DATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_STACK) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned"); + +ASSERT(_stext % 4 == 0, " +ERROR(riscv-rt): `_stext` must be 4-byte aligned"); + +ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, " +BUG(riscv-rt): .data is not 4-byte aligned"); + +ASSERT(_sidata % 4 == 0, " +BUG(riscv-rt): the LMA of .data is not 4-byte aligned"); + +ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, " +BUG(riscv-rt): .bss is not 4-byte aligned"); + +ASSERT(_sheap % 4 == 0, " +BUG(riscv-rt): start of .heap is not 4-byte aligned"); + +ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), " +ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region. +Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'"); + +ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, " +ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts. +Consider changing `_max_hart_id` or `_hart_stack_size`."); + +ASSERT(SIZEOF(.got) == 0, " +.got section detected in the input files. Dynamic relocations are not +supported. If you are linking to C code compiled using the `gcc` crate +then modify your build script to compile the C code _without_ the +-fPIC flag. See the documentation of the `gcc::Config.fpic` method for +details."); + +/* Do not exceed this mark in the error messages above | */ \ No newline at end of file diff --git a/esp32c3-hal/src/gpio.rs b/esp32c3-hal/src/gpio.rs new file mode 100644 index 00000000000..e8ed69a99b8 --- /dev/null +++ b/esp32c3-hal/src/gpio.rs @@ -0,0 +1,165 @@ +use esp_hal_common::gpio::gpio; + +use crate::hal_gpio::*; + +type OutputSignalType = u8; +const OUTPUT_SIGNAL_MAX: u8 = 128; +const INPUT_SIGNAL_MAX: u8 = 100; + +#[allow(non_camel_case_types)] +#[derive(Clone, Copy, PartialEq)] +pub enum InputSignal { + SPIQ = 0, + SPID = 1, + SPIHD = 2, + SPIWP = 3, + U0RXD = 6, + U0CTS = 7, + U0DSR = 8, + U1RXD = 9, + U1CTS = 10, + U1DSR = 11, + I2S_MCLK = 12, + I2SO_BCK = 13, + I2SO_WS = 14, + I2SI_SD = 15, + I2SI_BCK = 16, + I2SI_WS = 17, + GPIO_BT_PRIORITY = 18, + GPIO_BT_ACTIVE = 19, + CPU_GPIO_0 = 28, + CPU_GPIO_1 = 29, + CPU_GPIO_2 = 30, + CPU_GPIO_3 = 31, + CPU_GPIO_4 = 32, + CPU_GPIO_5 = 33, + CPU_GPIO_6 = 34, + CPU_GPIO_7 = 35, + EXT_ADC_START = 45, + RMT_SIG_0 = 51, + RMT_SIG_1 = 52, + I2CEXT0_SCL = 53, + I2CEXT0_SDA = 54, + FSPICLK = 63, + FSPIQ = 64, + FSPID = 65, + FSPIHD = 66, + FSPIWP = 67, + FSPICS0 = 68, + TWAI_RX = 74, + SIG_FUNC_97 = 97, + SIG_FUNC_98 = 98, + SIG_FUNC_99 = 99, + SIG_FUNC_100 = 100, +} + +#[allow(non_camel_case_types)] +#[derive(Clone, Copy, PartialEq)] +pub enum OutputSignal { + SPIQ = 0, + SPID = 1, + SPIHD = 2, + SPIWP = 3, + SPICLK_MUX = 4, + SPICS0 = 5, + U0TXD = 6, + U0RTS = 7, + U0DTR = 8, + U1TXD = 9, + U1RTS = 10, + U1DTR = 11, + I2S_MCLK = 12, + I2SO_BCK = 13, + I2SO_WS = 14, + I2SI_SD = 15, + I2SI_BCK = 16, + I2SI_WS = 17, + GPIO_WLAN_PRIO = 18, + GPIO_WLAN_ACTIVE = 19, + CPU_GPIO_0 = 28, + CPU_GPIO_1 = 29, + CPU_GPIO_2 = 30, + CPU_GPIO_3 = 31, + CPU_GPIO_4 = 32, + CPU_GPIO_5 = 33, + CPU_GPIO_6 = 34, + CPU_GPIO_7 = 35, + USB_JTAG_TCK = 36, + USB_JTAG_TMS = 37, + USB_JTAG_TDI = 38, + USB_JTAG_TDO = 39, + LEDC_LS_SIG0 = 45, + LEDC_LS_SIG1 = 46, + LEDC_LS_SIG2 = 47, + LEDC_LS_SIG3 = 48, + LEDC_LS_SIG4 = 49, + LEDC_LS_SIG5 = 50, + RMT_SIG_0 = 51, + RMT_SIG_1 = 52, + I2CEXT0_SCL = 53, + I2CEXT0_SDA = 54, + GPIO_SD0 = 55, + GPIO_SD1 = 56, + GPIO_SD2 = 57, + GPIO_SD3 = 58, + I2SO_SD1 = 59, + FSPICLK_MUX = 63, + FSPIQ = 64, + FSPID = 65, + FSPIHD = 66, + FSPIWP = 67, + FSPICS0 = 68, + FSPICS1 = 69, + FSPICS3 = 70, + FSPICS2 = 71, + FSPICS4 = 72, + FSPICS5 = 73, + TWAI_TX = 74, + TWAI_BUS_OFF_ON = 75, + TWAI_CLKOUT = 76, + ANT_SEL0 = 89, + ANT_SEL1 = 90, + ANT_SEL2 = 91, + ANT_SEL3 = 92, + ANT_SEL4 = 93, + ANT_SEL5 = 94, + ANT_SEL6 = 95, + ANT_SEL7 = 96, + SIG_FUNC_97 = 97, + SIG_FUNC_98 = 98, + SIG_FUNC_99 = 99, + SIG_FUNC_100 = 100, + CLK_OUT1 = 123, + CLK_OUT2 = 124, + CLK_OUT3 = 125, + SPICS1 = 126, + USB_JTAG_TRST = 127, + GPIO = 128, +} + +gpio! { + Function1, + SingleCore, + Gpio0: (gpio0, 0, gpio[0], IO, RTC, Bank0), + Gpio1: (gpio1, 1, gpio[1], IO, RTC, Bank0), + Gpio2: (gpio2, 2, gpio[2], IO, RTC, Bank0), (FSPIQ: Function2), (FSPIQ: Function2), + Gpio3: (gpio3, 3, gpio[3], IO, RTC, Bank0), + Gpio4: (gpio4, 4, gpio[4], IO, RTC, Bank0), (FSPIHD: Function2), (USB_JTAG_TMS: Function0, FSPIHD: Function2), + Gpio5: (gpio5, 5, gpio[5], IO, RTC, Bank0), (FSPIWP: Function2), (USB_JTAG_TDI: Function0, FSPIWP: Function2), + Gpio6: (gpio6, 6, gpio[6], IO, 0, Bank0), (FSPICLK: Function2), (USB_JTAG_TCK: Function0, FSPICLK_MUX: Function2), + Gpio7: (gpio7, 7, gpio[7], IO, 0, Bank0), (FSPID: Function2), (USB_JTAG_TDO: Function0, FSPID: Function2), + Gpio8: (gpio8, 8, gpio[8], IO, 0, Bank0), + Gpio9: (gpio9, 9, gpio[9], IO, 0, Bank0), + Gpio10: (gpio10, 10, gpio[10], IO, 0, Bank0), (FSPICS0: Function2), (FSPICS0: Function2), + Gpio11: (gpio11, 11, gpio[11], IO, 0, Bank0), + Gpio12: (gpio12, 12, gpio[12], IO, 0, Bank0), (SPIHD: Function0), (SPIHD: Function0), + Gpio13: (gpio13, 13, gpio[13], IO, 0, Bank0), (SPIWP: Function0), (SPIWP: Function0), + Gpio14: (gpio14, 14, gpio[14], IO, 0, Bank0), (), (SPICS0: Function0), + Gpio15: (gpio15, 15, gpio[15], IO, 0, Bank0), (), (SPICLK_MUX: Function0), + Gpio16: (gpio16, 16, gpio[16], IO, 0, Bank0), (SPID: Function0), (SPID: Function0), + Gpio17: (gpio17, 17, gpio[17], IO, 0, Bank0), (SPIQ: Function0), (SPIQ: Function0), + Gpio18: (gpio18, 18, gpio[18], IO, 0, Bank0), + Gpio19: (gpio19, 19, gpio[19], IO, 0, Bank0), + Gpio20: (gpio20, 20, gpio[20], IO, 0, Bank0), (U0RXD: Function0), (), + Gpio21: (gpio21, 21, gpio[21], IO, 0, Bank0), (), (U0TXD: Function0), +} diff --git a/esp32c3-hal/src/gpio/mod.rs b/esp32c3-hal/src/gpio/mod.rs deleted file mode 100644 index d086249ef74..00000000000 --- a/esp32c3-hal/src/gpio/mod.rs +++ /dev/null @@ -1,698 +0,0 @@ -use core::{convert::Infallible, marker::PhantomData}; - -use embedded_hal::digital::v2::{OutputPin as _, StatefulOutputPin as _}; - -use crate::pac::{GPIO, IO_MUX}; - -mod mux; -pub use mux::*; - -pub use crate::prelude::*; - -#[allow(dead_code)] -pub struct IO { - io_mux: IO_MUX, - pub pins: Pins, -} - -impl IO { - pub fn new(gpio: GPIO, io_mux: IO_MUX) -> Self { - let pins = gpio.split(); - let io = IO { io_mux, pins }; - - io - } -} - -pub trait GpioExt { - type Parts; - - fn split(self) -> Self::Parts; -} - -pub trait Pin { - fn sleep_mode(&mut self, on: bool) -> &mut Self; - - fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self; - - fn listen(&mut self, event: Event) { - self.listen_with_options(event, true, false, false) - } - - fn listen_with_options( - &mut self, - event: Event, - int_enable: bool, - nmi_enable: bool, - wake_up_from_light_sleep: bool, - ); - - fn unlisten(&mut self); - - fn clear_interrupt(&mut self); - - fn is_interrupt_set(&mut self) -> bool; - - fn is_non_maskable_interrupt_set(&mut self) -> bool; - - fn enable_hold(&mut self, on: bool); -} - -pub trait InputPin: Pin { - fn set_to_input(&mut self) -> &mut Self; - - fn enable_input(&mut self, on: bool) -> &mut Self; - - fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self; - - fn is_input_high(&mut self) -> bool; - - fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { - self.connect_input_to_peripheral_with_options(signal, false, false) - } - - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - ) -> &mut Self; -} - -pub trait OutputPin: Pin { - fn set_to_open_drain_output(&mut self) -> &mut Self; - - fn set_to_push_pull_output(&mut self) -> &mut Self; - - fn enable_output(&mut self, on: bool) -> &mut Self; - - fn set_output_high(&mut self, on: bool) -> &mut Self; - - fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self; - - fn enable_open_drain(&mut self, on: bool) -> &mut Self; - - fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self; - - fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self; - - fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self; - - fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { - self.connect_peripheral_to_output_with_options(signal, false, false, false, false) - } - - fn connect_peripheral_to_output_with_options( - &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, - ) -> &mut Self; - - fn internal_pull_up(&mut self, on: bool) -> &mut Self; - - fn internal_pull_down(&mut self, on: bool) -> &mut Self; -} - -pub trait RTCPin {} - -pub trait AnalogPin {} - -#[derive(Copy, Clone)] -pub enum Event { - RisingEdge = 1, - FallingEdge = 2, - AnyEdge = 3, - LowLevel = 4, - HighLevel = 5, -} - -pub struct Unknown {} - -pub struct Input { - _mode: PhantomData, -} - -pub struct RTCInput { - _mode: PhantomData, -} - -pub struct Floating; - -pub struct PullDown; - -pub struct PullUp; - -pub struct Output { - _mode: PhantomData, -} - -pub struct RTCOutput { - _mode: PhantomData, -} - -pub struct OpenDrain; - -pub struct PushPull; - -pub struct Analog; - -pub struct Alternate { - _mode: PhantomData, -} - -pub struct AF0; - -pub struct AF1; - -pub struct AF2; - -pub enum DriveStrength { - I5mA = 0, - I10mA = 1, - I20mA = 2, - I40mA = 3, -} - -#[derive(PartialEq)] -pub enum AlternateFunction { - Function0 = 0, - Function1 = 1, - Function2 = 2, -} - -pub fn connect_low_to_peripheral(signal: InputSignal) { - unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { - w.sig_in_sel() - .set_bit() - .func_in_inv_sel() - .bit(false) - .func_in_sel() - .bits(0x1f) - }); -} - -pub fn connect_high_to_peripheral(signal: InputSignal) { - unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { - w.sig_in_sel() - .set_bit() - .func_in_inv_sel() - .bit(false) - .func_in_sel() - .bits(0x1e) - }); -} - -macro_rules! impl_output { - ( - $pxi:ident: - ( - $pin_num:expr, $bit:expr, $out_en_set:ident, $out_en_clear:ident, - $out_set:ident, $out_clear:ident, $out_reg:ident - ) - $( ,( $( $af_signal:ident: $af:ident ),* ))? - ) => { - impl embedded_hal::digital::v2::OutputPin for $pxi> { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Self::Error> { - unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) }; - Ok(()) - } - - fn set_low(&mut self) -> Result<(), Self::Error> { - unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) }; - Ok(()) - } - } - - impl embedded_hal::digital::v2::StatefulOutputPin for $pxi> { - fn is_set_high(&self) -> Result { - unsafe { Ok((*GPIO::ptr()).$out_reg.read().bits() & (1 << $bit) != 0) } - } - - fn is_set_low(&self) -> Result { - Ok(!self.is_set_high()?) - } - } - - impl embedded_hal::digital::v2::ToggleableOutputPin for $pxi> { - type Error = Infallible; - - fn toggle(&mut self) -> Result<(), Self::Error> { - if self.is_set_high()? { - Ok(self.set_low()?) - } else { - Ok(self.set_high()?) - } - } - } - - impl $pxi { - pub fn into_pull_up_input(self) -> $pxi> { - self.init_input(false, false); - $pxi { _mode: PhantomData } - } - - pub fn into_pull_down_input(self) -> $pxi> { - self.init_input(true, false); - $pxi { _mode: PhantomData } - } - - fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { - let gpio = unsafe { &*GPIO::ptr() }; - let iomux = unsafe { &*IO_MUX::ptr() }; - - gpio.$out_en_set.write(|w| unsafe { w.bits(1 << $bit) }); - gpio.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(open_drain)); - gpio.func_out_sel_cfg[$pin_num] - .modify(|_, w| unsafe { w.func_out_sel().bits(OutputSignal::GPIO as u8) }); - - iomux.gpio[$pin_num].modify(|_, w| unsafe { - w.mcu_sel() - .bits(alternate as u8) - .fun_ie() - .clear_bit() - .fun_wpd() - .clear_bit() - .fun_wpu() - .clear_bit() - .fun_drv() - .bits(DriveStrength::I20mA as u8) - .slp_sel() - .clear_bit() - }); - } - - pub fn into_push_pull_output(self) -> $pxi> { - self.init_output(AlternateFunction::Function1, false); - $pxi { _mode: PhantomData } - } - - pub fn into_open_drain_output(self) -> $pxi> { - self.init_output(AlternateFunction::Function1, true); - $pxi { _mode: PhantomData } - } - - pub fn into_alternate_1(self) -> $pxi> { - self.init_output(AlternateFunction::Function1, false); - $pxi { _mode: PhantomData } - } - - pub fn into_alternate_2(self) -> $pxi> { - self.init_output(AlternateFunction::Function2, false); - $pxi { _mode: PhantomData } - } - } - - impl OutputPin for $pxi { - fn set_to_open_drain_output(&mut self) -> &mut Self { - self.init_output(AlternateFunction::Function1, true); - self - } - - fn set_to_push_pull_output(&mut self) -> &mut Self { - self.init_output(AlternateFunction::Function1, false); - self - } - - fn enable_output(&mut self, on: bool) -> &mut Self { - if on { - unsafe { &*GPIO::ptr() } - .$out_en_set - .write(|w| unsafe { w.bits(1 << $bit) }); - } else { - unsafe { &*GPIO::ptr() } - .$out_en_clear - .write(|w| unsafe { w.bits(1 << $bit) }); - } - self - } - - fn set_output_high(&mut self, high: bool) -> &mut Self { - if high { - unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) }; - } else { - unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) }; - } - self - } - - fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) }); - self - } - - fn enable_open_drain(&mut self, on: bool) -> &mut Self { - unsafe { &*GPIO::ptr() }.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(on)); - self - } - - fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.mcu_wpu().bit(on)); - self - } - - fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.mcu_wpd().bit(on)); - self - } - - fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.mcu_oe().bit(on)); - self - } - - fn connect_peripheral_to_output_with_options( - &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, - ) -> &mut Self { - let af = if force_via_gpio_mux { - AlternateFunction::Function1 - } else { - match signal { - $( $( - OutputSignal::$af_signal => AlternateFunction::$af, - )* )? - _ => AlternateFunction::Function1 - } - }; - - if af == AlternateFunction::Function1 && signal as usize > 128 { - panic!("Cannot connect this peripheral to GPIO"); - } - - self.set_alternate_function(af); - - let clipped_signal = if signal as usize <= 128 { signal as u8 } else { 128u8 }; - - unsafe { &*GPIO::ptr() }.func_out_sel_cfg[$pin_num].modify(|_, w| unsafe { - w - .func_out_sel().bits(clipped_signal) - .func_out_inv_sel().bit(invert) - .func_oen_sel().bit(enable_from_gpio) - .func_oen_inv_sel().bit(invert_enable) - }); - - self - } - - fn internal_pull_up(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() }.gpio[$pin_num].modify(|_, w| w.fun_wpu().bit(on)); - self - } - - fn internal_pull_down(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() }.gpio[$pin_num].modify(|_, w| w.fun_wpd().bit(on)); - self - } - } - }; -} - -macro_rules! impl_input { - ($pxi:ident: - ($pin_num:expr, $bit:expr, $out_en_clear:ident, $reg:ident, $reader:ident, - $status_w1tc:ident, $pcpu_int:ident, $pcpu_nmi:ident - ) $( ,( $( $af_signal:ident : $af:ident ),* ))? - ) => { - impl embedded_hal::digital::v2::InputPin for $pxi> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(unsafe { &*GPIO::ptr() }.$reg.read().$reader().bits() & (1 << $bit) != 0) - } - - fn is_low(&self) -> Result { - Ok(!self.is_high()?) - } - } - - impl $pxi { - fn init_input(&self, pull_down: bool, pull_up: bool) { - let gpio = unsafe { &*GPIO::ptr() }; - let iomux = unsafe { &*IO_MUX::ptr() }; - - - gpio.$out_en_clear - .write(|w| unsafe { w.bits(1 << $bit) }); - - gpio.func_out_sel_cfg[$pin_num] - .modify(|_, w| unsafe { w.func_out_sel().bits(OutputSignal::GPIO as u8) }); - - iomux.gpio[$pin_num].modify(|_, w| unsafe { - w.mcu_sel() - .bits(2) - .fun_ie() - .set_bit() - .fun_wpd() - .bit(pull_down) - .fun_wpu() - .bit(pull_up) - .slp_sel() - .clear_bit() - }); - } - - pub fn into_floating_input(self) -> $pxi> { - self.init_input(false, false); - $pxi { _mode: PhantomData } - } - } - - impl InputPin for $pxi { - fn set_to_input(&mut self) -> &mut Self { - self.init_input(false, false); - self - } - - fn enable_input(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.fun_ie().bit(on)); - self - } - - fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.mcu_ie().bit(on)); - self - } - - fn is_input_high(&mut self) -> bool { - unsafe { &*GPIO::ptr() }.$reg.read().$reader().bits() & (1 << $bit) != 0 - } - - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - ) -> &mut Self { - - let af = if force_via_gpio_mux - { - AlternateFunction::Function1 - } - else { - match signal { - $( $( - InputSignal::$af_signal => AlternateFunction::$af, - )* )? - _ => AlternateFunction::Function1 - } - }; - - if af == AlternateFunction::Function1 && signal as usize >= 128 { - panic!("Cannot connect GPIO to this peripheral"); - } - - self.set_alternate_function(af); - - if (signal as usize) < 128 { - unsafe { &*GPIO::ptr() }.func_in_sel_cfg[signal as usize].modify(|_, w| unsafe { - w.sig_in_sel() - .set_bit() - .func_in_inv_sel() - .bit(invert) - .func_in_sel() - .bits($pin_num) - }); - } - self - } - } - - impl Pin for $pxi { - fn sleep_mode(&mut self, on: bool) -> &mut Self { - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| w.slp_sel().bit(on)); - self - } - - fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self { - - unsafe { &*IO_MUX::ptr() } - .gpio[$pin_num] - .modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) }); - self - } - - fn listen_with_options(&mut self, event: Event, - int_enable: bool, nmi_enable: bool, - wake_up_from_light_sleep: bool - ) { - if wake_up_from_light_sleep { - match event { - Event::AnyEdge | Event::RisingEdge | Event::FallingEdge => { - panic!("Edge triggering is not supported for wake-up from light sleep"); - }, - _ => {} - } - } - unsafe { - (&*GPIO::ptr()).pin[$pin_num].modify(|_, w| - w - .pin_int_ena().bits(int_enable as u8 | ((nmi_enable as u8) << 1)) - .pin_int_type().bits(event as u8) - .pin_wakeup_enable().bit(wake_up_from_light_sleep) - ); - } - } - - fn unlisten(&mut self) { - unsafe { (&*GPIO::ptr()).pin[$pin_num].modify(|_, w| - w.pin_int_ena().bits(0).pin_int_type().bits(0).pin_int_ena().bits(0) ); - } - } - - fn clear_interrupt(&mut self) { - unsafe {&*GPIO::ptr()}.$status_w1tc.write(|w| - unsafe {w.bits(1 << $bit)}) - } - - fn is_interrupt_set(&mut self) -> bool { - (unsafe {&*GPIO::ptr()}.$pcpu_int.read().bits() & (1 << $bit)) !=0 - } - - fn is_non_maskable_interrupt_set(&mut self) -> bool { - (unsafe {&*GPIO::ptr()}.$pcpu_nmi.read().bits() & (1 << $bit)) !=0 - } - - fn enable_hold(&mut self, _on: bool) { - - - todo!(); - } - } - }; -} - -macro_rules! impl_pin_wrap { - ($pxi:ident, $pin_num:expr, IO - $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? - ) => { - impl_input!($pxi: ($pin_num, $pin_num % 32, enable_w1tc, in_, data_next, - status_w1tc, pcpu_int, pcpu_nmi_int) - $( ,( $( $af_input_signal: $af_input ),* ) )? ); - }; -} - -macro_rules! impl_output_wrap { - ($pxi:ident, $pin_num:expr, IO - $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? - ) => { - impl_output!($pxi: - ($pin_num, $pin_num % 32, enable_w1ts, enable_w1tc, out_w1ts, out_w1tc, out) - - $( ,( $( $af_output_signal: $af_output ),* ) )? ); - }; -} - -macro_rules! gpio { - ( $($pxi:ident: ($pname:ident, $pin_num:literal, - $type:ident, $rtc:tt ), - $( - ( $( $af_input_signal:ident: $af_input:ident ),* ), - $( - ( $( $af_output_signal:ident: $af_output:ident ),* ), - )? - )? - )+ ) => { - - impl GpioExt for GPIO { - type Parts = Pins; - - fn split(self) -> Self::Parts { - Pins { - $( - $pname: $pxi { _mode: PhantomData }, - )+ - } - } - } - - - pub struct Pins { - $( - - pub $pname: $pxi, - )+ - } - - - - $( - - pub struct $pxi { - _mode: PhantomData, - } - - impl_pin_wrap!($pxi, $pin_num, $type - $( ,( $( $af_input_signal: $af_input ),* ) )? ); - impl_output_wrap!($pxi, $pin_num, $type - $($( ,( $( $af_output_signal: $af_output ),* ) )? )? ); - )+ - }; -} - -gpio! { - Gpio0: (gpio0, 0, IO, RTC), - Gpio1: (gpio1, 1, IO, RTC), - Gpio2: (gpio2, 2, IO, RTC), (FSPIQ: Function2), (FSPIQ: Function2), - Gpio3: (gpio3, 3, IO, RTC), - Gpio4: (gpio4, 4, IO, RTC), (FSPIHD: Function2), (USB_JTAG_TMS: Function0, FSPIHD: Function2), - Gpio5: (gpio5, 5, IO, RTC), (FSPIWP: Function2), (USB_JTAG_TDI: Function0, FSPIWP: Function2), - Gpio6: (gpio6, 6, IO, 0), (FSPICLK: Function2), (USB_JTAG_TCK: Function0, FSPICLK_MUX: Function2), - Gpio7: (gpio7, 7, IO, 0), (FSPID: Function2), (USB_JTAG_TDO: Function0, FSPID: Function2), - Gpio8: (gpio8, 8, IO, 0), - Gpio9: (gpio9, 9, IO, 0), - Gpio10: (gpio10, 10, IO, 0), (FSPICS0: Function2), (FSPICS0: Function2), - Gpio11: (gpio11, 11, IO, 0), - Gpio12: (gpio12, 12, IO, 0), (SPIHD: Function0), (SPIHD: Function0), - Gpio13: (gpio13, 13, IO, 0), (SPIWP: Function0), (SPIWP: Function0), - Gpio14: (gpio14, 14, IO, 0), (), (SPICS0: Function0), - Gpio15: (gpio15, 15, IO, 0), (), (SPICLK_MUX: Function0), - Gpio16: (gpio16, 16, IO, 0), (SPID: Function0), (SPID: Function0), - Gpio17: (gpio17, 17, IO, 0), (SPIQ: Function0), (SPIQ: Function0), - Gpio18: (gpio18, 18, IO, 0), - Gpio19: (gpio19, 19, IO, 0), - Gpio20: (gpio20, 20, IO, 0), (U0RXD: Function0), (), - Gpio21: (gpio21, 21, IO, 0), (), (U0TXD: Function0), -} diff --git a/esp32c3-hal/src/gpio/mux.rs b/esp32c3-hal/src/gpio/mux.rs deleted file mode 100644 index 8468831e39b..00000000000 --- a/esp32c3-hal/src/gpio/mux.rs +++ /dev/null @@ -1,130 +0,0 @@ -#[allow(non_camel_case_types)] -#[derive(Clone, Copy, PartialEq)] -pub enum InputSignal { - SPIQ = 0, - SPID = 1, - SPIHD = 2, - SPIWP = 3, - U0RXD = 6, - U0CTS = 7, - U0DSR = 8, - U1RXD = 9, - U1CTS = 10, - U1DSR = 11, - I2S_MCLK = 12, - I2SO_BCK = 13, - I2SO_WS = 14, - I2SI_SD = 15, - I2SI_BCK = 16, - I2SI_WS = 17, - GPIO_BT_PRIORITY = 18, - GPIO_BT_ACTIVE = 19, - CPU_GPIO_0 = 28, - CPU_GPIO_1 = 29, - CPU_GPIO_2 = 30, - CPU_GPIO_3 = 31, - CPU_GPIO_4 = 32, - CPU_GPIO_5 = 33, - CPU_GPIO_6 = 34, - CPU_GPIO_7 = 35, - EXT_ADC_START = 45, - RMT_SIG_0 = 51, - RMT_SIG_1 = 52, - I2CEXT0_SCL = 53, - I2CEXT0_SDA = 54, - FSPICLK = 63, - FSPIQ = 64, - FSPID = 65, - FSPIHD = 66, - FSPIWP = 67, - FSPICS0 = 68, - TWAI_RX = 74, - SIG_FUNC_97 = 97, - SIG_FUNC_98 = 98, - SIG_FUNC_99 = 99, - SIG_FUNC_100 = 100, -} - -#[allow(non_camel_case_types)] -#[derive(Clone, Copy, PartialEq)] -pub enum OutputSignal { - SPIQ = 0, - SPID = 1, - SPIHD = 2, - SPIWP = 3, - SPICLK_MUX = 4, - SPICS0 = 5, - U0TXD = 6, - U0RTS = 7, - U0DTR = 8, - U1TXD = 9, - U1RTS = 10, - U1DTR = 11, - I2S_MCLK = 12, - I2SO_BCK = 13, - I2SO_WS = 14, - I2SI_SD = 15, - I2SI_BCK = 16, - I2SI_WS = 17, - GPIO_WLAN_PRIO = 18, - GPIO_WLAN_ACTIVE = 19, - CPU_GPIO_0 = 28, - CPU_GPIO_1 = 29, - CPU_GPIO_2 = 30, - CPU_GPIO_3 = 31, - CPU_GPIO_4 = 32, - CPU_GPIO_5 = 33, - CPU_GPIO_6 = 34, - CPU_GPIO_7 = 35, - USB_JTAG_TCK = 36, - USB_JTAG_TMS = 37, - USB_JTAG_TDI = 38, - USB_JTAG_TDO = 39, - LEDC_LS_SIG0 = 45, - LEDC_LS_SIG1 = 46, - LEDC_LS_SIG2 = 47, - LEDC_LS_SIG3 = 48, - LEDC_LS_SIG4 = 49, - LEDC_LS_SIG5 = 50, - RMT_SIG_0 = 51, - RMT_SIG_1 = 52, - I2CEXT0_SCL = 53, - I2CEXT0_SDA = 54, - GPIO_SD0 = 55, - GPIO_SD1 = 56, - GPIO_SD2 = 57, - GPIO_SD3 = 58, - I2SO_SD1 = 59, - FSPICLK_MUX = 63, - FSPIQ = 64, - FSPID = 65, - FSPIHD = 66, - FSPIWP = 67, - FSPICS0 = 68, - FSPICS1 = 69, - FSPICS3 = 70, - FSPICS2 = 71, - FSPICS4 = 72, - FSPICS5 = 73, - TWAI_TX = 74, - TWAI_BUS_OFF_ON = 75, - TWAI_CLKOUT = 76, - ANT_SEL0 = 89, - ANT_SEL1 = 90, - ANT_SEL2 = 91, - ANT_SEL3 = 92, - ANT_SEL4 = 93, - ANT_SEL5 = 94, - ANT_SEL6 = 95, - ANT_SEL7 = 96, - SIG_FUNC_97 = 97, - SIG_FUNC_98 = 98, - SIG_FUNC_99 = 99, - SIG_FUNC_100 = 100, - CLK_OUT1 = 123, - CLK_OUT2 = 124, - CLK_OUT3 = 125, - SPICS1 = 126, - USB_JTAG_TRST = 127, - GPIO = 128, -} diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index 5df2582f55a..e9edbce5dd7 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -1,10 +1,10 @@ #![no_std] pub use embedded_hal as ehal; -pub use esp_hal_common::{pac, prelude, Serial, Timer}; +pub use esp_hal_common::{gpio as hal_gpio, pac, prelude, Serial, Timer}; -pub mod gpio; pub mod rtc_cntl; -pub use gpio::IO; +pub mod gpio; + pub use rtc_cntl::RtcCntl; diff --git a/esp32c3-hal/src/rtc_cntl.rs b/esp32c3-hal/src/rtc_cntl.rs index c8080944036..a2e28733f78 100644 --- a/esp32c3-hal/src/rtc_cntl.rs +++ b/esp32c3-hal/src/rtc_cntl.rs @@ -30,9 +30,13 @@ impl RtcCntl { pub fn set_wdt_enable(&self, enable: bool) { self.set_wdt_write_protection(false); - self.rtc_cntl - .rtc_wdtconfig0 - .write(|w| w.wdt_en().bit(enable)); + if !enable { + self.rtc_cntl.rtc_wdtconfig0.write(|w| unsafe { w.bits(0) }); + } else { + self.rtc_cntl + .rtc_wdtconfig0 + .write(|w| w.wdt_en().bit(enable)); + } self.set_wdt_write_protection(true); }