121 lines
3.3 KiB
Rust
121 lines
3.3 KiB
Rust
#![no_std]
|
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
|
|
use gpio::Port;
|
|
pub use va108xx;
|
|
pub use va108xx as pac;
|
|
|
|
pub mod clock;
|
|
pub mod gpio;
|
|
pub mod i2c;
|
|
pub mod prelude;
|
|
pub mod pwm;
|
|
pub mod spi;
|
|
pub mod sysconfig;
|
|
pub mod time;
|
|
pub mod timer;
|
|
pub mod typelevel;
|
|
pub mod uart;
|
|
|
|
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum FunSel {
|
|
Sel0 = 0b00,
|
|
Sel1 = 0b01,
|
|
Sel2 = 0b10,
|
|
Sel3 = 0b11,
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum PeripheralSelect {
|
|
PortA = 0,
|
|
PortB = 1,
|
|
Spi0 = 4,
|
|
Spi1 = 5,
|
|
Spi2 = 6,
|
|
Uart0 = 8,
|
|
Uart1 = 9,
|
|
I2c0 = 16,
|
|
I2c1 = 17,
|
|
Irqsel = 21,
|
|
Ioconfig = 22,
|
|
Utility = 23,
|
|
Gpio = 24,
|
|
}
|
|
|
|
/// Generic interrupt config which can be used to specify whether the HAL driver will
|
|
/// use the IRQSEL register to route an interrupt, and whether the IRQ will be unmasked in the
|
|
/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to
|
|
/// perform those steps themselves.
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub struct InterruptConfig {
|
|
/// Interrupt target vector. Should always be set, might be required for disabling IRQs
|
|
pub id: pac::Interrupt,
|
|
/// Specfiy whether IRQ should be routed to an IRQ vector using the IRQSEL peripheral.
|
|
pub route: bool,
|
|
/// Specify whether the IRQ is unmasked in the Cortex-M NVIC. If an interrupt is used for
|
|
/// multiple purposes, the user can enable the interrupts themselves.
|
|
pub enable_in_nvic: bool,
|
|
}
|
|
|
|
impl InterruptConfig {
|
|
pub fn new(id: pac::Interrupt, route: bool, enable_in_nvic: bool) -> Self {
|
|
InterruptConfig {
|
|
id,
|
|
route,
|
|
enable_in_nvic,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type IrqCfg = InterruptConfig;
|
|
|
|
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
#[error("invalid pin with number {0}")]
|
|
pub struct InvalidPinError(u8);
|
|
|
|
/// Can be used to manually manipulate the function select of port pins.
|
|
///
|
|
/// The function selection table can be found on p.36 of the programmers guide. Please note
|
|
/// that most of the structures and APIs in this library will automatically correctly configure
|
|
/// the pin or statically expect the correct pin type.
|
|
pub fn port_function_select(
|
|
ioconfig: &mut pac::Ioconfig,
|
|
port: Port,
|
|
pin: u8,
|
|
funsel: FunSel,
|
|
) -> Result<(), InvalidPinError> {
|
|
if (port == Port::A && pin >= 32) || (port == Port::B && pin >= 24) {
|
|
return Err(InvalidPinError(pin));
|
|
}
|
|
|
|
let reg_block = match port {
|
|
Port::A => ioconfig.porta(pin as usize),
|
|
Port::B => ioconfig.portb0(pin as usize),
|
|
};
|
|
|
|
reg_block.modify(|_, w| unsafe { w.funsel().bits(funsel as u8) });
|
|
Ok(())
|
|
}
|
|
|
|
/// Enable a specific interrupt using the NVIC peripheral.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// This function is `unsafe` because it can break mask-based critical sections.
|
|
#[inline]
|
|
pub unsafe fn enable_nvic_interrupt(irq: pac::Interrupt) {
|
|
unsafe {
|
|
cortex_m::peripheral::NVIC::unmask(irq);
|
|
}
|
|
}
|
|
|
|
/// Disable a specific interrupt using the NVIC peripheral.
|
|
#[inline]
|
|
pub fn disable_nvic_interrupt(irq: pac::Interrupt) {
|
|
cortex_m::peripheral::NVIC::mask(irq);
|
|
}
|