13: Smaller tweaks r=robamu a=robamu



Co-authored-by: Robin Mueller <robin.mueller.m@gmail.com>
This commit is contained in:
bors[bot] 2021-11-11 19:03:42 +00:00 committed by GitHub
commit 1c31e9177d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 34 deletions

View File

@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased] ## [unreleased]
### Changed
- Minor optimizations and tweaks for GPIO module
## [0.2.0] ## [0.2.0]

View File

@ -1,3 +1,6 @@
//! # API for clock related functionality
//!
//! This also includes functionality to enable the peripheral clocks
use crate::time::Hertz; use crate::time::Hertz;
use cortex_m::interrupt::{self, Mutex}; use cortex_m::interrupt::{self, Mutex};
use once_cell::unsync::OnceCell; use once_cell::unsync::OnceCell;

View File

@ -1,12 +1,12 @@
//! # GPIO module //! # API for the GPIO peripheral
//! //!
//! The implementation of this GPIO module is heavily based on the //! The implementation of this GPIO module is heavily based on the
//! [ATSAMD HAL implementation](https://docs.rs/atsamd-hal/0.13.0/atsamd_hal/gpio/v2/index.html). //! [ATSAMD HAL implementation](https://docs.rs/atsamd-hal/0.13.0/atsamd_hal/gpio/v2/index.html).
//! //!
//! This API provides two different submodules, [`pin`] and [`dynpin`], //! This API provides two different submodules, [`pins`] and [`dynpins`],
//! representing two different ways to handle GPIO pins. The default, [`pin`], //! representing two different ways to handle GPIO pins. The default, [`pins`],
//! is a type-level API that tracks the state of each pin at compile-time. The //! is a type-level API that tracks the state of each pin at compile-time. The
//! alternative, [`dynpin`] is a type-erased, value-level API that tracks the //! alternative, [`dynpins`] is a type-erased, value-level API that tracks the
//! state of each pin at run-time. //! state of each pin at run-time.
//! //!
//! The type-level API is strongly preferred. By representing the state of each //! The type-level API is strongly preferred. By representing the state of each
@ -14,7 +14,7 @@
//! compile-time. Furthermore, the type-level API has absolutely zero run-time //! compile-time. Furthermore, the type-level API has absolutely zero run-time
//! cost. //! cost.
//! //!
//! If needed, [`dynpin`] can be used to erase the type-level differences //! If needed, [`dynpins`] can be used to erase the type-level differences
//! between pins. However, by doing so, pins must now be tracked at run-time, //! between pins. However, by doing so, pins must now be tracked at run-time,
//! and each pin has a non-zero memory footprint. //! and each pin has a non-zero memory footprint.
//! //!

View File

@ -84,15 +84,8 @@
//! This module also provides additional, type-level tools to work with GPIO //! This module also provides additional, type-level tools to work with GPIO
//! pins. //! pins.
//! //!
//! The [`OptionalPinId`] and [`OptionalPin`] traits use the [`OptionalKind`] //! The [`AnyPin`] trait defines an [`AnyKind`] type class
//! pattern to act as type-level versions of [`Option`] for `PinId` and `Pin`
//! respectively. And the [`AnyPin`] trait defines an [`AnyKind`] type class
//! for all `Pin` types. //! for all `Pin` types.
//!
//! [type classes]: crate::typelevel#type-classes
//! [type-level enum]: crate::typelevel#type-level-enum
//! [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
use super::dynpins::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode}; use super::dynpins::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
use super::reg::RegisterInterface; use super::reg::RegisterInterface;
@ -115,14 +108,12 @@ pub enum PinState {
} }
/// GPIO error type /// GPIO error type
///
/// [`DynPin`]s are not tracked and verified at compile-time, so run-time
/// operations are fallible. This `enum` represents the corresponding errors.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum PinError { pub enum PinError {
/// The pin did not have the correct ID or mode for the requested operation /// The pin did not have the correct ID or mode for the requested operation.
/// [`DynPin`](crate::gpio::DynPin)s are not tracked and verified at compile-time, so run-time
/// operations are fallible.
InvalidPinType, InvalidPinType,
InputDisabledForOutput,
IsMasked, IsMasked,
} }

View File

@ -200,11 +200,13 @@ pub(super) unsafe trait RegisterInterface {
} }
} }
#[inline]
fn get_perid(&self) -> u32 { fn get_perid(&self) -> u32 {
let portreg = self.port_reg(); let portreg = self.port_reg();
portreg.perid.read().bits() portreg.perid.read().bits()
} }
#[inline]
/// Read the logic level of an output pin /// Read the logic level of an output pin
fn read_pin(&self) -> bool { fn read_pin(&self) -> bool {
let portreg = self.port_reg(); let portreg = self.port_reg();
@ -220,27 +222,25 @@ pub(super) unsafe trait RegisterInterface {
/// Read a pin but use the masked version but check whether the datamask for the pin is /// Read a pin but use the masked version but check whether the datamask for the pin is
/// cleared as well /// cleared as well
#[inline]
fn read_pin_masked(&self) -> Result<bool, PinError> { fn read_pin_masked(&self) -> Result<bool, PinError> {
if !self.datamask() { if !self.datamask() {
Err(PinError::IsMasked) Err(PinError::IsMasked)
} else { } else {
let portreg = self.port_reg(); Ok(((self.port_reg().datain().read().bits() >> self.id().num) & 0x01) == 1)
Ok(((portreg.datain().read().bits() >> self.id().num) & 0x01) == 1)
} }
} }
/// Write the logic level of an output pin /// Write the logic level of an output pin
#[inline] #[inline]
fn write_pin(&mut self, bit: bool) { fn write_pin(&mut self, bit: bool) {
let portreg = self.port_reg();
let mask = self.mask_32();
// Safety: SETOUT is a "mask" register, and we only write the bit for // Safety: SETOUT is a "mask" register, and we only write the bit for
// this pin ID // this pin ID
unsafe { unsafe {
if bit { if bit {
portreg.setout().write(|w| w.bits(mask)); self.port_reg().setout().write(|w| w.bits(self.mask_32()));
} else { } else {
portreg.clrout().write(|w| w.bits(mask)); self.port_reg().clrout().write(|w| w.bits(self.mask_32()));
} }
} }
} }
@ -252,15 +252,13 @@ pub(super) unsafe trait RegisterInterface {
if !self.datamask() { if !self.datamask() {
Err(PinError::IsMasked) Err(PinError::IsMasked)
} else { } else {
let portreg = self.port_reg();
let mask = self.mask_32();
// Safety: SETOUT is a "mask" register, and we only write the bit for // Safety: SETOUT is a "mask" register, and we only write the bit for
// this pin ID // this pin ID
unsafe { unsafe {
if bit { if bit {
portreg.setout().write(|w| w.bits(mask)); self.port_reg().setout().write(|w| w.bits(self.mask_32()));
} else { } else {
portreg.clrout().write(|w| w.bits(mask)); self.port_reg().clrout().write(|w| w.bits(self.mask_32()));
} }
Ok(()) Ok(())
} }
@ -270,18 +268,15 @@ pub(super) unsafe trait RegisterInterface {
/// Toggle the logic level of an output pin /// Toggle the logic level of an output pin
#[inline] #[inline]
fn toggle(&mut self) { fn toggle(&mut self) {
let portreg = self.port_reg();
let mask = self.mask_32();
// Safety: TOGOUT is a "mask" register, and we only write the bit for // Safety: TOGOUT is a "mask" register, and we only write the bit for
// this pin ID // this pin ID
unsafe { portreg.togout().write(|w| w.bits(mask)) }; unsafe { self.port_reg().togout().write(|w| w.bits(self.mask_32())) };
} }
/// Only useful for input pins /// Only useful for input pins
#[inline] #[inline]
fn filter_type(&self, filter: FilterType, clksel: FilterClkSel) { fn filter_type(&self, filter: FilterType, clksel: FilterClkSel) {
let iocfg = self.iocfg_port(); self.iocfg_port().port[self.id().num as usize].modify(|_, w| {
iocfg.port[self.id().num as usize].modify(|_, w| {
// Safety: Only write to register for this Pin ID // Safety: Only write to register for this Pin ID
unsafe { unsafe {
w.flttype().bits(filter as u8); w.flttype().bits(filter as u8);

View File

@ -1,4 +1,7 @@
//! API for the UART peripheral //! # API for the UART peripheral
//!
//! ## Examples
//! - [UART example](https://github.com/robamu-org/va108xx-hal-rs/blob/main/examples/uart.rs)
use core::{convert::Infallible, ptr}; use core::{convert::Infallible, ptr};
use core::{marker::PhantomData, ops::Deref}; use core::{marker::PhantomData, ops::Deref};
use libm::floorf; use libm::floorf;