Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
peripheral macro
* Add peripheral generation macro
  • Loading branch information
MabezDev committed Dec 12, 2022
commit 080f4aef66b4b88f478f0c8f0961f559555abed4
73 changes: 14 additions & 59 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@
#![cfg_attr(xtensa, feature(asm_experimental_arch))]

#[cfg(esp32)]
pub use esp32 as pac;
pub(crate) use esp32 as pac;
#[cfg(esp32c2)]
pub use esp32c2 as pac;
pub(crate) use esp32c2 as pac;
#[cfg(esp32c3)]
pub use esp32c3 as pac;
pub(crate) use esp32c3 as pac;
#[cfg(esp32s2)]
pub use esp32s2 as pac;
pub(crate) use esp32s2 as pac;
#[cfg(esp32s3)]
pub use esp32s3 as pac;
pub(crate) use esp32s3 as pac;

#[cfg_attr(esp32, path = "peripherals/esp32.rs")]
#[cfg_attr(esp32c3, path = "peripherals/esp32c3.rs")]
#[cfg_attr(esp32c2, path = "peripherals/esp32c2.rs")]
#[cfg_attr(esp32s2, path = "peripherals/esp32s2.rs")]
#[cfg_attr(esp32s3, path = "peripherals/esp32s3.rs")]
pub mod peripherals;

pub use procmacros as macros;

#[cfg(rmt)]
Expand All @@ -43,7 +51,7 @@ pub use self::{
interrupt::*,
rng::Rng,
rtc_cntl::{Rtc, Rwdt},
uart::Serial,
uart::Uart,
spi::Spi,
timer::Timer,
};
Expand Down Expand Up @@ -237,56 +245,3 @@ mod critical_section_impl {
}
}
}

#[macro_export]
#[allow(unused_macros)]
macro_rules! into_ref {
($($name:ident),*) => {
$(
let $name = $name.into_ref();
)*
}
}

#[allow(unused_macros)]
macro_rules! impl_peripheral_trait {
($type:ident) => {
unsafe impl Send for $type {}

impl $crate::peripheral::sealed::Sealed for $type {}

impl $crate::peripheral::Peripheral for $type {
type P = $type;

#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
$type { ..*self }
}
}
};
}

#[allow(unused_macros)]
macro_rules! impl_peripheral {
($type:ident) => {
pub struct $type(::core::marker::PhantomData<*const ()>);

impl $type {
/// # Safety
///
/// Care should be taken not to instnatiate this peripheral instance, if it
/// is already instantiated and used elsewhere
#[inline(always)]
pub unsafe fn new() -> Self {
$type(::core::marker::PhantomData)
}
}

$crate::impl_peripheral_trait!($type);
};
}

#[allow(unused_imports)]
pub(crate) use impl_peripheral;
#[allow(unused_imports)]
pub(crate) use impl_peripheral_trait;
156 changes: 145 additions & 11 deletions esp-hal-common/src/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,152 @@ pub trait Peripheral: Sized + sealed::Sealed {

impl<T: DerefMut> sealed::Sealed for T {}

impl<T: DerefMut> Peripheral for T
where
T::Target: Peripheral,
{
type P = <T::Target as Peripheral>::P;
pub(crate) mod sealed {
pub trait Sealed {}
}

#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
self.deref_mut().clone_unchecked()
mod peripheral_macros {
#[macro_export]
macro_rules! peripherals {
($($(#[$cfg:meta])? $name:ident),*$(,)?) => {
#[allow(non_snake_case)]
pub struct Peripherals {
$(
$(#[$cfg])?
pub $name: peripherals::$name,
)*
}

impl Peripherals {
// /// Returns all the peripherals *once*
// #[inline]
// pub fn take() -> Self {

// #[no_mangle]
// static mut _ESP_HAL_DEVICE_PERIPHERALS: bool = false;

// critical_section::with(|_| unsafe {
// if _ESP_HAL_DEVICE_PERIPHERALS {
// panic!("init called more than once!")
// }
// _ESP_HAL_DEVICE_PERIPHERALS = true;
// Self::steal()
// })
// }

pub fn take() -> Option<Self> {
#[no_mangle]
static mut _ESP_HAL_DEVICE_PERIPHERALS: bool = false;
critical_section::with(|_| unsafe {
if _ESP_HAL_DEVICE_PERIPHERALS {
return None;
}
_ESP_HAL_DEVICE_PERIPHERALS = true;
Some(Peripherals::steal())
})
}
}

impl Peripherals {
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self {
$(
$(#[$cfg])?
// $name: peripherals::$name::steal(), // FIXME add this back once we have removed pac::Peripherals completely
$name: unsafe { core::mem::zeroed() }, // this is well defined for zero sized types: https://github.com/rust-lang/unsafe-code-guidelines/issues/250
)*
}
}
}

// expose the new structs
$(
pub use peripherals::$name;
)*
}
}
}

pub(crate) mod sealed {
pub trait Sealed {}
#[macro_export]
macro_rules! create_peripherals {
($($(#[$cfg:meta])? $name:ident),*$(,)?) => {
$(
$(#[$cfg])?
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct $name { _inner: () }

$(#[$cfg])?
impl $name {
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self { _inner: () }
}

#[doc = r"Pointer to the register block"]
pub const PTR: *const <super::pac::$name as core::ops::Deref>::Target = super::pac::$name::PTR;

#[doc = r"Return the pointer to the register block"]
#[inline(always)]
pub const fn ptr() -> *const <super::pac::$name as core::ops::Deref>::Target {
super::pac::$name::PTR
}
}

impl core::ops::Deref for $name {
type Target = <super::pac::$name as core::ops::Deref>::Target;

fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}

impl core::ops::DerefMut for $name {

fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(Self::PTR as *mut _) }
}
}

impl crate::peripheral::Peripheral for $name {
type P = $name;

#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self::steal()
}
}

impl crate::peripheral::Peripheral for &mut $name {
type P = $name;

#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
$name::steal()
}
}


)*
}
}

#[macro_export]
macro_rules! into_ref {
($($name:ident),*) => {
$(
let $name = $name.into_ref();
)*
}
}
}
59 changes: 59 additions & 0 deletions esp-hal-common/src/peripherals/esp32.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

use crate::pac;

pub use pac::Interrupt; // We need to export this for users to use

crate::peripherals! {
AES,
APB_CTRL,
BB,
DPORT,
EFUSE,
FLASH_ENCRYPTION,
FRC_TIMER,
GPIO,
GPIO_SD,
HINF,
I2C0,
I2C1,
I2S0,
I2S1,
IO_MUX,
LEDC,
PWM0,
PWM1,
NRX,
PCNT,
RMT,
RNG,
RSA,
RTC_CNTL,
RTCIO,
RTC_I2C,
SDMMC,
SENS,
SHA,
SLC,
SLCHOST,
SPI0,
SPI1,
SPI2,
SPI3,
TIMG0,
TIMG1,
TWAI,
UART0,
UART1,
UART2,
UHCI0,
UHCI1,
}

mod peripherals {
pub use super::pac::*;

crate::create_peripherals! {
UART0,
UART1,
}
}
41 changes: 41 additions & 0 deletions esp-hal-common/src/peripherals/esp32c2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

use crate::pac;

pub use pac::Interrupt; // We need to export this for users to use

crate::peripherals! {
APB_CTRL,
APB_SARADC,
ASSIST_DEBUG,
DMA,
ECC,
EFUSE,
EXTMEM,
GPIO,
I2C0,
INTERRUPT_CORE0,
IO_MUX,
LEDC,
RNG,
RTC_CNTL,
SENSITIVE,
SHA,
SPI0,
SPI1,
SPI2,
SYSTEM,
SYSTIMER,
TIMG0,
UART0,
UART1,
XTS_AES,
}

mod peripherals {
pub use super::pac::*;

crate::create_peripherals! {
UART0,
UART1,
}
}
Loading