Skip to content

Commit

Permalink
Add additional API docs, function attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
mciantyre committed Nov 7, 2022
1 parent f227302 commit 8b7721d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
12 changes: 12 additions & 0 deletions raltool/src/generate/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ pub fn render(_opts: &super::Options, _ir: &IR, d: &Device) -> Result<TokenStrea
impl crate::Valid for #name {}

impl #name {
/// Acquire a vaild, but possibly aliased, instance.
///
/// # Safety
///
/// See [the struct-level safety documentation](crate::Instance).
#[inline]
pub const unsafe fn instance() -> Self {
Instance::new(#name)
}
Expand Down Expand Up @@ -152,6 +158,12 @@ name."#
impl crate::private::Sealed for #name {}
impl crate::Valid for #name {}
impl #name {
/// Acquire a vaild, but possibly aliased, instance.
///
/// # Safety
///
/// See [the struct-level safety documentation](crate::Instance).
#[inline]
pub const unsafe fn instance() -> Self {
Instance::new(#name)
}
Expand Down
71 changes: 67 additions & 4 deletions raltool/src/generate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,33 +141,96 @@ pub fn render(ir: &IR, opts: &Options) -> Result<()> {

root.items.extend(quote!(
#![no_std]
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, clippy::self_named_constructors, clippy::module_inception)]

pub use ral_registers::{RWRegister, RORegister, WORegister, read_reg, write_reg, modify_reg};

/// An owned peripheral of type `T`, instance `N`.
///
/// Fabricating an `Instance` is always `unsafe`. An owner of an
/// `Instance` may assume that
///
/// - the underlying pointer points to a static register block of type `T`.
/// - the instance number `N` properly describes the peripheral instance.
/// - they own _all_ registers pointed at by `T`.
///
/// Owners use this guarantee to safely access the peripheral registers.
/// However, nothing guarantees any of these except for your diligence.
///
/// Constructing an `Instance` is zero cost. Additionally, `Instance` is transparent
/// and amenable to null-pointer optimizations.
///
/// See the package-level documentation for more information on fabricating
/// instances.
///
/// # Safety of `new()`.
///
/// By calling `new()`, you claim
///
/// 1. `ptr` points to static memory that can be described by a type `T`.
/// 2. The instance number `N` correctly describes `ptr`.
/// 3. You are becoming the sole owner of this instance.
///
/// # Safety of `instance()`
///
/// The various `instance()` methods handle safety concerns 1 and 2 from `new()`.
/// By their construction, each `instance()` implementation provides a pointer to valid
/// peripheral memory, and associates the correct `N` with that pointer. Therefore,
/// you're only responsible for ensuring safety concern 3 from `new()`.
#[repr(transparent)]
pub struct Instance<T, const N: u8> {
ptr: *const T,
ptr: core::ptr::NonNull<T>,
}

impl<T, const N: u8> core::ops::Deref for Instance<T, N> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
// Safety: User provided a pointer that points to static MMIO.
// This implies non-null, initialized, aligned, and dereferenceable.
unsafe { self.ptr.as_ref() }
}
}

impl<T, const N: u8> Instance<T, N> {
/// Create an arbitrary `Instance` from a pointer to `T`.
///
/// # Safety
///
/// See [the struct docs](Instance) for the safety contract.
#[inline]
pub const unsafe fn new(ptr: *const T) -> Self {
Self { ptr }
// Casting *const _ to *mut _ is OK. The mutable pointer never
// escapes Instance.
Self { ptr: core::ptr::NonNull::new_unchecked(ptr as *mut _) }
}
}

unsafe impl<T, const N: u8> Send for Instance<T, N> {}

/// The instance number for a peripheral singleton.
///
/// If your peripheral only has one instance, it's given
/// this number. The CCM peripheral is a good example of
/// a peripheral that uses this constant.
///
/// See the package documentation for more information on
/// this constant.
pub const SOLE_INSTANCE: u8 = 0u8;
mod private {
pub trait Sealed {}
}

/// Vouches for an `Instance<T, N>`'s validity.
///
/// This trait is implemented for all `Instance<T, N>` supported
/// by your chip. Note that the implementation may change when
/// selecting new chip features. For instance, i.MX RT 1011 chips
/// do not have LPUART 4 through 8. So, `Valid` is _not_ implemented
/// for `lpuart::Instance<4>` through `lpuart::Instance<8>`.
///
/// See the package documentation for more information on how
/// to use this trait in your APIs.
pub trait Valid : private::Sealed {}
));

Expand Down

0 comments on commit 8b7721d

Please sign in to comment.