Update and improve HAL library and docs
All checks were successful
Rust/va108xx-rs/pipeline/pr-main This commit looks good

This commit is contained in:
2024-07-04 17:10:01 +02:00
parent abb78c2682
commit 3c8c455c6f
32 changed files with 1541 additions and 1378 deletions

View File

@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [v0.7.0] 2024-07-04
- Replace `uarta` and `uartb` `Uart` constructors by `new` constructor
- Replace SPI `spia`, `spib` and `spic` constructors by `new` constructor
- Replace I2C `i2ca`, `i2cb` constructors by `new` constructor. Update constructor
to fail on invalid fast I2C speed system clock values
- Renamed `gpio::pins` to `gpio::pin` and `gpio::dynpins` to `gpio::dynpin`
## [v0.6.0] 2024-06-16
- Updated `embedded-hal` to v1

View File

@ -1,6 +1,6 @@
[package]
name = "va108xx-hal"
version = "0.6.0"
version = "0.7.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2021"
description = "HAL for the Vorago VA108xx family of microcontrollers"

View File

@ -57,7 +57,7 @@
//! [InvalidPinTypeError].
use super::{
pins::{FilterType, InterruptEdge, InterruptLevel, Pin, PinId, PinMode, PinState},
pin::{FilterType, InterruptEdge, InterruptLevel, Pin, PinId, PinMode, PinState},
reg::RegisterInterface,
};
use crate::{clock::FilterClkSel, pac, FunSel, IrqCfg};

View File

@ -3,10 +3,10 @@
//! The implementation of this GPIO module is heavily based on the
//! [ATSAMD HAL implementation](https://docs.rs/atsamd-hal/latest/atsamd_hal/gpio/index.html).
//!
//! This API provides two different submodules, [`mod@pins`] and [`dynpins`],
//! representing two different ways to handle GPIO pins. The default, [`mod@pins`],
//! This API provides two different submodules, [pin] and [dynpin],
//! representing two different ways to handle GPIO pins. The default, [pin],
//! is a type-level API that tracks the state of each pin at compile-time. The
//! alternative, [`dynpins`] is a type-erased, value-level API that tracks the
//! alternative, [dynpin] is a type-erased, value-level API that tracks the
//! state of each pin at run-time.
//!
//! 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
//! cost.
//!
//! If needed, [`dynpins`] can be used to erase the type-level differences
//! If needed, [dynpin] can be used to erase the type-level differences
//! between pins. However, by doing so, pins must now be tracked at run-time,
//! and each pin has a non-zero memory footprint.
//!
@ -101,10 +101,10 @@ macro_rules! common_reg_if_functions {
};
}
pub mod dynpins;
pub use dynpins::*;
pub mod dynpin;
pub use dynpin::*;
pub mod pins;
pub use pins::*;
pub mod pin;
pub use pin::*;
mod reg;

View File

@ -70,7 +70,7 @@
//! This module implements all of the embedded HAL GPIO traits for each [`Pin`]
//! in the corresponding [`PinMode`]s, namely: [`InputPin`], [`OutputPin`],
//! and [`StatefulOutputPin`].
use super::dynpins::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
use super::dynpin::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
use super::reg::RegisterInterface;
use crate::{
pac::{Irqsel, Porta, Portb, Sysconfig},

View File

@ -1,5 +1,5 @@
use super::dynpins::{self, DynGroup, DynPinId, DynPinMode};
use super::pins::{FilterType, InterruptEdge, InterruptLevel, PinState};
use super::dynpin::{self, DynGroup, DynPinId, DynPinMode};
use super::pin::{FilterType, InterruptEdge, InterruptLevel, PinState};
use super::IsMaskedError;
use crate::clock::FilterClkSel;
use va108xx::{ioconfig, porta};
@ -30,7 +30,7 @@ impl From<DynPinMode> for ModeFields {
use DynPinMode::*;
match mode {
Input(config) => {
use dynpins::DynInput::*;
use dynpin::DynInput::*;
fields.dir = false;
match config {
Floating => (),
@ -44,7 +44,7 @@ impl From<DynPinMode> for ModeFields {
}
}
Output(config) => {
use dynpins::DynOutput::*;
use dynpin::DynOutput::*;
fields.dir = true;
match config {
PushPull => (),

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,5 @@
//! Prelude
pub use fugit::ExtU32 as _;
pub use fugit::RateExtU32 as _;
pub use crate::time::*;

View File

@ -4,7 +4,7 @@
//!
//! ## Examples
//!
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/examples/pwm.rs)
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/pwm.rs)
use core::convert::Infallible;
use core::marker::PhantomData;
@ -158,9 +158,9 @@ where
{
/// Create a new stronlgy typed PWM pin
pub fn new(
vtp: (Pin, Tim),
sys_clk: impl Into<Hertz> + Copy,
sys_cfg: &mut pac::Sysconfig,
sys_clk: impl Into<Hertz> + Copy,
tim_and_pin: (Pin, Tim),
initial_period: impl Into<Hertz> + Copy,
) -> Self {
let mut pin = PwmPin {
@ -171,7 +171,7 @@ where
current_rst_val: 0,
sys_clk: sys_clk.into(),
},
reg: unsafe { TimAndPinRegister::new(vtp.0, vtp.1) },
reg: unsafe { TimAndPinRegister::new(tim_and_pin.0, tim_and_pin.1) },
mode: PhantomData,
};
enable_peripheral_clock(sys_cfg, crate::clock::PeripheralClocks::Gpio);
@ -225,12 +225,13 @@ where
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
{
pub fn pwma(
vtp: (Pin, Tim),
sys_clk: impl Into<Hertz> + Copy,
sys_cfg: &mut pac::Sysconfig,
sys_clk: impl Into<Hertz> + Copy,
pin_and_tim: (Pin, Tim),
initial_period: impl Into<Hertz> + Copy,
) -> Self {
let mut pin: PwmPin<Pin, Tim, PwmA> = Self::new(vtp, sys_clk, sys_cfg, initial_period);
let mut pin: PwmPin<Pin, Tim, PwmA> =
Self::new(sys_cfg, sys_clk, pin_and_tim, initial_period);
pin.enable_pwm_a();
pin
}
@ -241,12 +242,13 @@ where
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
{
pub fn pwmb(
vtp: (Pin, Tim),
sys_clk: impl Into<Hertz> + Copy,
sys_cfg: &mut pac::Sysconfig,
sys_clk: impl Into<Hertz> + Copy,
pin_and_tim: (Pin, Tim),
initial_period: impl Into<Hertz> + Copy,
) -> Self {
let mut pin: PwmPin<Pin, Tim, PwmB> = Self::new(vtp, sys_clk, sys_cfg, initial_period);
let mut pin: PwmPin<Pin, Tim, PwmB> =
Self::new(sys_cfg, sys_clk, pin_and_tim, initial_period);
pin.enable_pwm_b();
pin
}

File diff suppressed because it is too large Load Diff

View File

@ -11,14 +11,15 @@ use libm::floorf;
pub use crate::IrqCfg;
use crate::{
clock::{self, enable_peripheral_clock, PeripheralClocks},
gpio::pins::{
clock::{enable_peripheral_clock, PeripheralClocks},
gpio::pin::{
AltFunc1, AltFunc2, AltFunc3, Pin, PA16, PA17, PA18, PA19, PA2, PA26, PA27, PA3, PA30,
PA31, PA8, PA9, PB18, PB19, PB20, PB21, PB22, PB23, PB6, PB7, PB8, PB9,
},
pac::{self, uarta as uart_base},
time::Hertz,
utility::unmask_irq,
PeripheralSelect,
};
//==================================================================================================
@ -306,7 +307,7 @@ pub struct UartBase<Uart> {
}
/// Serial abstraction. Entry point to create a new UART
pub struct Uart<Uart, Pins> {
uart_base: UartBase<Uart>,
inner: UartBase<Uart>,
pins: Pins,
}
@ -353,6 +354,7 @@ impl<UART> Tx<UART> {
pub trait Instance: Deref<Target = uart_base::RegisterBlock> {
fn ptr() -> *const uart_base::RegisterBlock;
const IDX: u8;
const PERIPH_SEL: PeripheralSelect;
}
impl<UART: Instance> UartBase<UART> {
@ -483,14 +485,34 @@ impl<UART: Instance> UartBase<UART> {
}
}
impl<UART, PINS> Uart<UART, PINS>
impl<UartInstance, PinsInstance> Uart<UartInstance, PinsInstance>
where
UART: Instance,
UartInstance: Instance,
PinsInstance: Pins<UartInstance>,
{
pub fn new(
syscfg: &mut va108xx::Sysconfig,
sys_clk: impl Into<Hertz>,
uart: UartInstance,
pins: PinsInstance,
config: impl Into<Config>,
) -> Self {
crate::clock::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
Uart {
inner: UartBase {
uart,
tx: Tx::new(),
rx: Rx::new(),
},
pins,
}
.init(config.into(), sys_clk.into())
}
/// This function assumes that the peripheral clock was alredy enabled
/// in the SYSCONFIG register
fn init(mut self, config: Config, sys_clk: Hertz) -> Self {
self.uart_base = self.uart_base.init(config, sys_clk);
self.inner = self.inner.init(config, sys_clk);
self
}
@ -501,7 +523,7 @@ where
irq_cfg: IrqCfg,
sys_cfg: Option<&mut pac::Sysconfig>,
irq_sel: Option<&mut pac::Irqsel>,
) -> UartWithIrq<UART, PINS> {
) -> UartWithIrq<UartInstance, PinsInstance> {
let (uart, pins) = self.downgrade_internal();
UartWithIrq {
pins,
@ -520,75 +542,75 @@ where
#[inline]
pub fn enable_rx(&mut self) {
self.uart_base.enable_rx();
self.inner.enable_rx();
}
#[inline]
pub fn disable_rx(&mut self) {
self.uart_base.enable_rx();
self.inner.enable_rx();
}
#[inline]
pub fn enable_tx(&mut self) {
self.uart_base.enable_tx();
self.inner.enable_tx();
}
#[inline]
pub fn disable_tx(&mut self) {
self.uart_base.disable_tx();
self.inner.disable_tx();
}
#[inline]
pub fn clear_rx_fifo(&mut self) {
self.uart_base.clear_rx_fifo();
self.inner.clear_rx_fifo();
}
#[inline]
pub fn clear_tx_fifo(&mut self) {
self.uart_base.clear_tx_fifo();
self.inner.clear_tx_fifo();
}
#[inline]
pub fn clear_rx_status(&mut self) {
self.uart_base.clear_rx_status();
self.inner.clear_rx_status();
}
#[inline]
pub fn clear_tx_status(&mut self) {
self.uart_base.clear_tx_status();
self.inner.clear_tx_status();
}
pub fn listen(&self, event: Event) {
self.uart_base.listen(event);
self.inner.listen(event);
}
pub fn unlisten(&self, event: Event) {
self.uart_base.unlisten(event);
self.inner.unlisten(event);
}
pub fn release(self) -> (UART, PINS) {
(self.uart_base.release(), self.pins)
pub fn release(self) -> (UartInstance, PinsInstance) {
(self.inner.release(), self.pins)
}
fn downgrade_internal(self) -> (UartBase<UART>, PINS) {
fn downgrade_internal(self) -> (UartBase<UartInstance>, PinsInstance) {
let base = UartBase {
uart: self.uart_base.uart,
tx: self.uart_base.tx,
rx: self.uart_base.rx,
uart: self.inner.uart,
tx: self.inner.tx,
rx: self.inner.rx,
};
(base, self.pins)
}
pub fn downgrade(self) -> UartBase<UART> {
pub fn downgrade(self) -> UartBase<UartInstance> {
UartBase {
uart: self.uart_base.uart,
tx: self.uart_base.tx,
rx: self.uart_base.rx,
uart: self.inner.uart,
tx: self.inner.tx,
rx: self.inner.rx,
}
}
pub fn split(self) -> (Tx<UART>, Rx<UART>) {
self.uart_base.split()
pub fn split(self) -> (Tx<UartInstance>, Rx<UartInstance>) {
self.inner.split()
}
}
@ -597,6 +619,8 @@ impl Instance for pac::Uarta {
pac::Uarta::ptr() as *const _
}
const IDX: u8 = 0;
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart0;
}
impl Instance for pac::Uartb {
@ -604,36 +628,8 @@ impl Instance for pac::Uartb {
pac::Uartb::ptr() as *const _
}
const IDX: u8 = 1;
}
macro_rules! uart_impl {
($($UARTX:path: ($uartx:ident, $clk_enb_enum:path),)+) => {
$(
impl<PINS: Pins<$UARTX>> Uart<$UARTX, PINS> {
pub fn $uartx(
uart: $UARTX,
pins: PINS,
config: impl Into<Config>,
syscfg: &mut pac::Sysconfig,
sys_clk: impl Into<Hertz>
) -> Self
{
enable_peripheral_clock(syscfg, $clk_enb_enum);
Uart {
uart_base: UartBase {
uart,
tx: Tx::new(),
rx: Rx::new(),
},
pins,
}
.init(config.into(), sys_clk.into())
}
}
)+
}
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart1;
}
impl<UART: Instance> UartWithIrqBase<UART> {
@ -871,10 +867,12 @@ impl<UART: Instance, PINS> UartWithIrq<UART, PINS> {
}
}
/*
uart_impl! {
pac::Uarta: (uarta, clock::PeripheralClocks::Uart0),
pac::Uartb: (uartb, clock::PeripheralClocks::Uart1),
}
*/
impl<Uart> Tx<Uart> where Uart: Instance {}