Skip to main content

vorago_shared_periphs/
lib.rs

1#![no_std]
2#[cfg(feature = "vor4x")]
3pub mod clock;
4pub mod embassy;
5pub mod gpio;
6pub mod i2c;
7pub mod ioconfig;
8pub mod pins;
9pub mod pwm;
10pub mod spi;
11pub mod sysconfig;
12pub mod time;
13pub mod timer;
14pub mod uart;
15
16pub use sysconfig::{
17    assert_peripheral_reset, deassert_peripheral_reset, disable_peripheral_clock,
18    enable_peripheral_clock, reset_peripheral_for_cycles,
19};
20
21#[cfg(not(feature = "_family-selected"))]
22compile_error!("no Vorago CPU family was select. Choices: vor1x or vor4x");
23
24pub use ioconfig::regs::FunSel;
25#[cfg(feature = "vor1x")]
26use va108xx as pac;
27#[cfg(feature = "vor4x")]
28use va416xx as pac;
29
30#[cfg(feature = "vor1x")]
31#[derive(Debug, Copy, Clone, PartialEq, Eq)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub enum PeripheralSelect {
34    PortA = 0,
35    PortB = 1,
36    Spi0 = 4,
37    Spi1 = 5,
38    Spi2 = 6,
39    Uart0 = 8,
40    Uart1 = 9,
41    I2c0 = 16,
42    I2c1 = 17,
43    Irqsel = 21,
44    IoConfig = 22,
45    Utility = 23,
46    Gpio = 24,
47}
48
49#[cfg(feature = "vor4x")]
50#[derive(Debug, Copy, Clone, PartialEq, Eq)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub enum PeripheralSelect {
53    Spi0 = 0,
54    Spi1 = 1,
55    Spi2 = 2,
56    Spi3 = 3,
57    Uart0 = 4,
58    Uart1 = 5,
59    Uart2 = 6,
60    I2c0 = 7,
61    I2c1 = 8,
62    I2c2 = 9,
63    Can0 = 10,
64    Can1 = 11,
65    Rng = 12,
66    Adc = 13,
67    Dac = 14,
68    Dma = 15,
69    Ebi = 16,
70    Eth = 17,
71    Spw = 18,
72    Clkgen = 19,
73    IrqRouter = 20,
74    IoConfig = 21,
75    Utility = 22,
76    Watchdog = 23,
77    PortA = 24,
78    PortB = 25,
79    PortC = 26,
80    PortD = 27,
81    PortE = 28,
82    PortF = 29,
83    PortG = 30,
84}
85
86cfg_if::cfg_if! {
87    if #[cfg(feature = "vor1x")] {
88        /// Number of GPIO ports and IOCONFIG registers for PORT A
89        pub const NUM_PORT_A: usize = 32;
90        /// Number of GPIO ports and IOCONFIG registers for PORT B
91        pub const NUM_PORT_B: usize = 24;
92    } else if #[cfg(feature = "vor4x")] {
93        /// Number of GPIO ports and IOCONFIG registers for PORT C to Port F
94        pub const NUM_PORT_DEFAULT: usize = 16;
95        /// Number of GPIO ports and IOCONFIG registers for PORT A
96        pub const NUM_PORT_A: usize = NUM_PORT_DEFAULT;
97        /// Number of GPIO ports and IOCONFIG registers for PORT B
98        pub const NUM_PORT_B: usize = NUM_PORT_DEFAULT;
99        /// Number of GPIO ports and IOCONFIG registers for PORT G
100        pub const NUM_PORT_G: usize = 8;
101    }
102}
103
104/// GPIO port enumeration.
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106#[cfg_attr(feature = "defmt", derive(defmt::Format))]
107pub enum Port {
108    A = 0,
109    B = 1,
110    #[cfg(feature = "vor4x")]
111    C = 2,
112    #[cfg(feature = "vor4x")]
113    D = 3,
114    #[cfg(feature = "vor4x")]
115    E = 4,
116    #[cfg(feature = "vor4x")]
117    F = 5,
118    #[cfg(feature = "vor4x")]
119    G = 6,
120}
121
122impl Port {
123    pub const fn max_offset(&self) -> usize {
124        match self {
125            Port::A => NUM_PORT_A,
126            Port::B => NUM_PORT_B,
127            #[cfg(feature = "vor4x")]
128            Port::C | Port::D | Port::E | Port::F => NUM_PORT_DEFAULT,
129            #[cfg(feature = "vor4x")]
130            Port::G => NUM_PORT_G,
131        }
132    }
133
134    /// Unsafely steal the GPIO peripheral block for the given port.
135    ///
136    /// # Safety
137    ///
138    /// Circumvents ownership and safety guarantees by the HAL.
139    pub unsafe fn steal_gpio(&self) -> gpio::regs::MmioGpio<'static> {
140        gpio::regs::Gpio::new_mmio(*self)
141    }
142}
143
144#[derive(Debug, thiserror::Error)]
145#[cfg_attr(feature = "defmt", derive(defmt::Format))]
146#[error("invalid GPIO offset {offset} for port {port:?}")]
147pub struct InvalidOffsetError {
148    offset: usize,
149    port: Port,
150}
151
152/// Generic interrupt config which can be used to specify whether the HAL driver will
153/// use the IRQSEL register to route an interrupt, and whether the IRQ will be unmasked in the
154/// Cortex-M0 NVIC. Both are generally necessary for IRQs to work, but the user might want to
155/// perform those steps themselves.
156#[cfg(feature = "vor1x")]
157#[derive(Debug, PartialEq, Eq, Clone, Copy)]
158#[cfg_attr(feature = "defmt", derive(defmt::Format))]
159pub struct InterruptConfig {
160    /// Interrupt target vector. Should always be set, might be required for disabling IRQs
161    pub id: va108xx::Interrupt,
162    /// Specfiy whether IRQ should be routed to an IRQ vector using the IRQSEL peripheral.
163    pub route: bool,
164    /// Specify whether the IRQ is unmasked in the Cortex-M NVIC. If an interrupt is used for
165    /// multiple purposes, the user can enable the interrupts themselves.
166    pub enable_in_nvic: bool,
167}
168
169#[cfg(feature = "vor1x")]
170impl InterruptConfig {
171    pub fn new(id: va108xx::Interrupt, route: bool, enable_in_nvic: bool) -> Self {
172        InterruptConfig {
173            id,
174            route,
175            enable_in_nvic,
176        }
177    }
178}
179
180/// Enable a specific interrupt using the NVIC peripheral.
181///
182/// # Safety
183///
184/// This function is `unsafe` because it can break mask-based critical sections.
185#[inline]
186pub unsafe fn enable_nvic_interrupt(irq: pac::Interrupt) {
187    unsafe {
188        cortex_m::peripheral::NVIC::unmask(irq);
189    }
190}
191
192/// Disable a specific interrupt using the NVIC peripheral.
193#[inline]
194pub fn disable_nvic_interrupt(irq: pac::Interrupt) {
195    cortex_m::peripheral::NVIC::mask(irq);
196}
197
198#[allow(dead_code)]
199pub(crate) mod sealed {
200    pub trait Sealed {}
201}
202
203pub(crate) mod shared {
204    use arbitrary_int::u5;
205
206    #[derive(Debug)]
207    pub struct TriggerLevel(arbitrary_int::UInt<u32, 5>);
208
209    impl TriggerLevel {
210        pub const fn new(value: u5) -> Self {
211            TriggerLevel(arbitrary_int::UInt::<u32, 5>::new(value.value() as u32))
212        }
213
214        pub const fn value(&self) -> u5 {
215            u5::new(self.0.value() as u8)
216        }
217    }
218
219    #[bitbybit::bitfield(u32, default = 0x0)]
220    #[derive(Debug)]
221    pub struct FifoClear {
222        #[bit(1, w)]
223        tx_fifo: bool,
224        #[bit(0, w)]
225        rx_fifo: bool,
226    }
227}