Implement IOMUX/GPIO for ESP32-C3, add blinky/serial_echo examples
This commit is contained in:
parent
22df2dbb99
commit
7fa2c4dbcf
30
esp32c3-hal/examples/blinky.rs
Normal file
30
esp32c3-hal/examples/blinky.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32c3_hal::{pac, prelude::*, RtcCntl, Timer, IO};
|
||||||
|
use nb::block;
|
||||||
|
use panic_halt as _;
|
||||||
|
use riscv_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
let rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
|
||||||
|
rtc_cntl.set_super_wdt_enable(false);
|
||||||
|
rtc_cntl.set_wdt_enable(false);
|
||||||
|
timer0.disable();
|
||||||
|
|
||||||
|
let mut led = io.pins.gpio2.into_push_pull_output();
|
||||||
|
led.set_high().unwrap();
|
||||||
|
|
||||||
|
timer0.start(10_000_000u64);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
led.toggle().unwrap();
|
||||||
|
block!(timer0.wait()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
25
esp32c3-hal/examples/serial_echo.rs
Normal file
25
esp32c3-hal/examples/serial_echo.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32c3_hal::{pac, prelude::*, RtcCntl, Serial, Timer};
|
||||||
|
use nb::block;
|
||||||
|
use panic_halt as _;
|
||||||
|
use riscv_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let rtccntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
|
||||||
|
rtccntl.set_super_wdt_enable(false);
|
||||||
|
rtccntl.set_wdt_enable(false);
|
||||||
|
timer0.disable();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let byte = block!(serial0.read()).unwrap();
|
||||||
|
block!(serial0.write(byte)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
698
esp32c3-hal/src/gpio/mod.rs
Normal file
698
esp32c3-hal/src/gpio/mod.rs
Normal file
@ -0,0 +1,698 @@
|
|||||||
|
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> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RTCInput<MODE> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Floating;
|
||||||
|
|
||||||
|
pub struct PullDown;
|
||||||
|
|
||||||
|
pub struct PullUp;
|
||||||
|
|
||||||
|
pub struct Output<MODE> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RTCOutput<MODE> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OpenDrain;
|
||||||
|
|
||||||
|
pub struct PushPull;
|
||||||
|
|
||||||
|
pub struct Analog;
|
||||||
|
|
||||||
|
pub struct Alternate<MODE> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<MODE> embedded_hal::digital::v2::OutputPin for $pxi<Output<MODE>> {
|
||||||
|
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<MODE> embedded_hal::digital::v2::StatefulOutputPin for $pxi<Output<MODE>> {
|
||||||
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
unsafe { Ok((*GPIO::ptr()).$out_reg.read().bits() & (1 << $bit) != 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(!self.is_set_high()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<MODE> embedded_hal::digital::v2::ToggleableOutputPin for $pxi<Output<MODE>> {
|
||||||
|
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<MODE> $pxi<MODE> {
|
||||||
|
pub fn into_pull_up_input(self) -> $pxi<Input<PullUp>> {
|
||||||
|
self.init_input(false, false);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_pull_down_input(self) -> $pxi<Input<PullDown>> {
|
||||||
|
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<Output<PushPull>> {
|
||||||
|
self.init_output(AlternateFunction::Function1, false);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_open_drain_output(self) -> $pxi<Output<OpenDrain>> {
|
||||||
|
self.init_output(AlternateFunction::Function1, true);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_alternate_1(self) -> $pxi<Alternate<AF1>> {
|
||||||
|
self.init_output(AlternateFunction::Function1, false);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_alternate_2(self) -> $pxi<Alternate<AF2>> {
|
||||||
|
self.init_output(AlternateFunction::Function2, false);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<MODE> OutputPin for $pxi<MODE> {
|
||||||
|
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<MODE> embedded_hal::digital::v2::InputPin for $pxi<Input<MODE>> {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(unsafe { &*GPIO::ptr() }.$reg.read().$reader().bits() & (1 << $bit) != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(!self.is_high()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<MODE> $pxi<MODE> {
|
||||||
|
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<Input<Floating>> {
|
||||||
|
self.init_input(false, false);
|
||||||
|
$pxi { _mode: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<MODE> InputPin for $pxi<MODE> {
|
||||||
|
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<MODE> Pin for $pxi<MODE> {
|
||||||
|
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<Unknown>,
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(
|
||||||
|
|
||||||
|
pub struct $pxi<MODE> {
|
||||||
|
_mode: PhantomData<MODE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
}
|
||||||
130
esp32c3-hal/src/gpio/mux.rs
Normal file
130
esp32c3-hal/src/gpio/mux.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#[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,
|
||||||
|
}
|
||||||
@ -4,6 +4,8 @@ pub use embedded_hal as ehal;
|
|||||||
pub use esp32c3 as pac;
|
pub use esp32c3 as pac;
|
||||||
pub use esp_hal_common::{prelude, Serial, Timer};
|
pub use esp_hal_common::{prelude, Serial, Timer};
|
||||||
|
|
||||||
|
pub mod gpio;
|
||||||
pub mod rtc_cntl;
|
pub mod rtc_cntl;
|
||||||
|
|
||||||
|
pub use gpio::IO;
|
||||||
pub use rtc_cntl::RtcCntl;
|
pub use rtc_cntl::RtcCntl;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user