va416xx_hal/
lib.rs

1//! This is the **H**ardware **A**bstraction **L**ayer (HAL) for the VA416xx MCU family.
2//!
3//! It is an additional hardware abstraction on top of the [peripheral access API](https://egit.irs.uni-stuttgart.de/rust/va416xx-rs/src/branch/main/va416xx).
4//!
5//! It is the result of reading the datasheet for the device and encoding a type-safe layer over the
6//! raw PAC. This crate also implements traits specified by the
7//! [embedded-hal](https://github.com/rust-embedded/embedded-hal) project, making it compatible with
8//! various drivers in the embedded rust ecosystem.
9//!
10//! It is generally advised to enable ONE of the following device features to use this crate
11//! depending on which chip you are using:
12//!
13//! - `va41630`
14//! - `va41629`
15//! - `va41628`
16//! - `va41620`
17//!
18//! If no option is specified, only access to APIs which are common for all families or
19//! which are not disabled for specific families is granted.
20//!
21//! When using this HAL and writing applications for the VA416xx family in general, it is strongly
22//! recommended that you set up the clock properly, because the default internal HBO clock
23//! is not very accurate. You can use the [crate::clock] module for this. If you are working
24//! with interrupts, it is strongly recommended to set up the IRQ router with the
25//! [crate::irq_router] module at the very least because that peripheral has confusing and/or
26//! faulty register reset values which might lead to weird bugs and glitches.
27#![no_std]
28#![cfg_attr(docsrs, feature(doc_auto_cfg))]
29#[cfg(feature = "alloc")]
30extern crate alloc;
31#[cfg(test)]
32extern crate std;
33
34use gpio::Port;
35pub use va416xx as device;
36pub use va416xx as pac;
37
38pub mod can;
39pub mod clock;
40pub mod dma;
41pub mod edac;
42pub mod gpio;
43pub mod i2c;
44pub mod irq_router;
45pub mod pins;
46pub mod prelude;
47pub mod pwm;
48pub mod spi;
49pub mod time;
50pub mod timer;
51pub mod uart;
52pub mod wdt;
53
54#[cfg(feature = "va41630")]
55pub mod nvm;
56
57#[cfg(not(feature = "va41628"))]
58pub mod adc;
59#[cfg(not(feature = "va41628"))]
60pub mod dac;
61
62pub use vorago_shared_hal::{
63    assert_peripheral_reset, deassert_peripheral_reset, disable_nvic_interrupt,
64    disable_peripheral_clock, enable_nvic_interrupt, enable_peripheral_clock,
65    reset_peripheral_for_cycles, FunctionSelect, PeripheralSelect,
66};
67
68#[derive(Debug, PartialEq, Eq, thiserror::Error)]
69#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70#[error("invalid pin with number {0}")]
71pub struct InvalidPinError(u8);
72
73/// Can be used to manually manipulate the function select of port pins.
74///
75/// The function selection table can be found on p.286 of the programmers guide. Please note
76/// that most of the structures and APIs in this library will automatically correctly configure
77/// the pin or statically expect the correct pin type.
78#[inline]
79pub fn port_function_select(
80    ioconfig: &mut pac::Ioconfig,
81    port: Port,
82    pin: u8,
83    funsel: FunctionSelect,
84) -> Result<(), InvalidPinError> {
85    if (port == Port::G && pin >= 8) || pin >= 16 {
86        return Err(InvalidPinError(pin));
87    }
88    let reg_block = match port {
89        Port::A => ioconfig.porta(pin as usize),
90        Port::B => ioconfig.portb(pin as usize),
91        Port::C => ioconfig.portc(pin as usize),
92        Port::D => ioconfig.portd(pin as usize),
93        Port::E => ioconfig.porte(pin as usize),
94        Port::F => ioconfig.portf(pin as usize),
95        Port::G => ioconfig.portg(pin as usize),
96    };
97
98    reg_block.modify(|_, w| unsafe { w.funsel().bits(funsel as u8) });
99    Ok(())
100}
101
102pub trait SyscfgExt {
103    fn enable_peripheral_clock(&mut self, clock: PeripheralSelect);
104
105    fn disable_peripheral_clock(&mut self, clock: PeripheralSelect);
106
107    fn assert_periph_reset(&mut self, periph: PeripheralSelect);
108
109    fn deassert_periph_reset(&mut self, periph: PeripheralSelect);
110
111    fn reset_peripheral_reset_for_cycles(&mut self, periph: PeripheralSelect, cycles: usize);
112}
113
114impl SyscfgExt for pac::Sysconfig {
115    #[inline(always)]
116    fn enable_peripheral_clock(&mut self, clock: PeripheralSelect) {
117        enable_peripheral_clock(clock)
118    }
119
120    #[inline(always)]
121    fn disable_peripheral_clock(&mut self, clock: PeripheralSelect) {
122        disable_peripheral_clock(clock)
123    }
124
125    #[inline(always)]
126    fn assert_periph_reset(&mut self, clock: PeripheralSelect) {
127        assert_peripheral_reset(clock)
128    }
129
130    #[inline(always)]
131    fn deassert_periph_reset(&mut self, clock: PeripheralSelect) {
132        deassert_peripheral_reset(clock)
133    }
134
135    #[inline(always)]
136    fn reset_peripheral_reset_for_cycles(&mut self, periph: PeripheralSelect, cycles: usize) {
137        reset_peripheral_for_cycles(periph, cycles)
138    }
139}