py32_hal/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![allow(async_fn_in_trait)]
3
4// This must go FIRST so that all the other modules see its macros.
5mod fmt;
6include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
7
8mod macros;
9use embassy_hal_internal::interrupt::Priority;
10pub use py32_metapac as pac;
11
12/// Operating modes for peripherals.
13pub mod mode {
14    trait SealedMode {}
15
16    /// Operating mode for a peripheral.
17    #[allow(private_bounds)]
18    pub trait Mode: SealedMode {}
19
20    macro_rules! impl_mode {
21        ($name:ident) => {
22            impl SealedMode for $name {}
23            impl Mode for $name {}
24        };
25    }
26
27    /// Blocking mode.
28    pub struct Blocking;
29    /// Async mode.
30    pub struct Async;
31
32    impl_mode!(Blocking);
33    impl_mode!(Async);
34}
35
36pub mod adc;
37pub mod dma;
38pub mod flash;
39pub mod gpio;
40pub mod i2c;
41pub mod rcc;
42pub mod timer;
43pub mod usart;
44
45#[cfg(any(feature = "embassy-usb-driver-impl", feature = "usb-device-impl"))]
46pub mod usb;
47
48#[cfg(feature = "exti")]
49pub mod exti;
50
51pub mod embassy;
52pub mod time;
53#[cfg(feature = "time-driver-systick")]
54pub use embassy::systick_time_driver;
55#[cfg(all(feature = "_time-driver", not(feature = "time-driver-systick")))]
56pub use embassy::time_driver;
57
58#[cfg(feature = "time-driver-systick")]
59use cortex_m::peripheral::SYST;
60
61/// `py32-hal` global configuration.
62#[non_exhaustive]
63#[derive(Clone, Copy)]
64pub struct Config {
65    /// RCC config.
66    pub rcc: rcc::Config,
67    /// Enable debug during sleep and stop.
68    ///
69    /// May increase power consumption. Defaults to true.
70    #[cfg(dbgmcu)]
71    pub enable_debug_during_sleep: bool,
72
73    // /// BDMA interrupt priority.
74    // ///
75    // /// Defaults to P0 (highest).
76    // #[cfg(bdma)]
77    // pub bdma_interrupt_priority: Priority,
78    /// DMA interrupt priority.
79    ///
80    /// Defaults to P0 (highest).
81    #[cfg(dma)]
82    pub dma_interrupt_priority: Priority,
83    // /// GPDMA interrupt priority.
84    // ///
85    // /// Defaults to P0 (highest).
86    // #[cfg(gpdma)]
87    // pub gpdma_interrupt_priority: Priority,
88}
89
90impl Default for Config {
91    fn default() -> Self {
92        Self {
93            rcc: Default::default(),
94            #[cfg(dbgmcu)]
95            enable_debug_during_sleep: true,
96            // #[cfg(any(stm32l4, stm32l5, stm32u5))]
97            // enable_independent_io_supply: true,
98            // #[cfg(bdma)]
99            // bdma_interrupt_priority: Priority::P0,
100            #[cfg(dma)]
101            dma_interrupt_priority: Priority::P0,
102            // #[cfg(gpdma)]
103            // gpdma_interrupt_priority: Priority::P0,
104        }
105    }
106}
107
108/// Initialize the `embassy-stm32` HAL with the provided configuration.
109///
110/// This returns the peripheral singletons that can be used for creating drivers.
111///
112/// This should only be called once at startup, otherwise it panics.
113pub fn init(config: Config, #[cfg(feature = "time-driver-systick")] systick: SYST) -> Peripherals {
114    critical_section::with(|cs| {
115        let p = Peripherals::take_with_cs(cs);
116        
117        rcc::enable_and_reset_with_cs::<peripherals::DBGMCU>(cs);
118        crate::pac::DBGMCU.cr().modify(|cr| {
119            #[cfg(dbgmcu_f072)]
120            cr.set_dbg_sleep(config.enable_debug_during_sleep);
121            cr.set_dbg_stop(config.enable_debug_during_sleep);
122        });
123
124        unsafe {
125            rcc::init(config.rcc);
126            crate::_generated::init_syscfg();
127
128            gpio::init(cs);
129
130            // must be after rcc init
131            #[cfg(all(feature = "_time-driver", not(feature = "time-driver-systick")))]
132            time_driver::init(cs);
133
134            #[cfg(feature = "time-driver-systick")]
135            systick_time_driver::init(cs, systick);
136
137            #[cfg(feature = "exti")]
138            exti::init(cs);
139
140            dma::init(cs, config.dma_interrupt_priority);
141        };
142        rcc::enable_and_reset_with_cs::<peripherals::FLASH>(cs);
143
144        p
145    })
146}
147
148// This must go last, so that it sees all the impl_foo! macros defined earlier.
149pub(crate) mod _generated {
150    #![allow(dead_code)]
151    #![allow(unused_imports)]
152    #![allow(non_snake_case)]
153    #![allow(missing_docs)]
154
155    include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
156}
157
158pub use crate::_generated::interrupt;
159
160pub use _generated::{peripherals, Peripherals};
161pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
162
163// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
164#[macro_export]
165macro_rules! bind_interrupts {
166    ($vis:vis struct $name:ident {
167        $(
168            $(#[cfg($cond_irq:meta)])?
169            $irq:ident => $(
170                $(#[cfg($cond_handler:meta)])?
171                $handler:ty
172            ),*;
173        )*
174    }) => {
175        #[derive(Copy, Clone)]
176        $vis struct $name;
177
178        $(
179            #[allow(non_snake_case)]
180            #[no_mangle]
181            $(#[cfg($cond_irq)])?
182            unsafe extern "C" fn $irq() {
183                $(
184                    $(#[cfg($cond_handler)])?
185                    <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
186
187                )*
188            }
189            $(#[cfg($cond_irq)])?
190            $crate::bind_interrupts!(@inner
191                $(
192                    $(#[cfg($cond_handler)])?
193                    unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
194                )*
195            );
196        )*
197    };
198    (@inner $($t:tt)*) => {
199        $($t)*
200    }
201}