py32_hal/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#![cfg_attr(not(test), no_std)]
#![allow(async_fn_in_trait)]

// This must go FIRST so that all the other modules see its macros.
mod fmt;
include!(concat!(env!("OUT_DIR"), "/_macros.rs"));

mod macros;

pub use py32_metapac as pac;


/// Operating modes for peripherals.
pub mod mode {
    trait SealedMode {}

    /// Operating mode for a peripheral.
    #[allow(private_bounds)]
    pub trait Mode: SealedMode {}

    macro_rules! impl_mode {
        ($name:ident) => {
            impl SealedMode for $name {}
            impl Mode for $name {}
        };
    }

    /// Blocking mode.
    pub struct Blocking;
    /// Async mode.
    pub struct Async;

    impl_mode!(Blocking);
    impl_mode!(Async);
}

pub mod time;
pub mod rcc;
pub mod i2c;
pub mod adc;
pub mod dma;
pub mod usart;
pub mod timer;
#[cfg(feature = "_time-driver")]
pub mod time_driver;
pub mod gpio;

#[cfg(feature = "exti")]
pub mod exti;

/// `py32-hal` global configuration.
#[non_exhaustive]
#[derive(Clone, Copy)]
pub struct Config {
    /// RCC config.
    pub rcc: rcc::Config,

    // /// Enable debug during sleep and stop.
    // ///
    // /// May increase power consumption. Defaults to true.
    // #[cfg(dbgmcu)]
    // pub enable_debug_during_sleep: bool,

    // /// BDMA interrupt priority.
    // ///
    // /// Defaults to P0 (highest).
    // #[cfg(bdma)]
    // pub bdma_interrupt_priority: Priority,

    // /// DMA interrupt priority.
    // ///
    // /// Defaults to P0 (highest).
    // #[cfg(dma)]
    // pub dma_interrupt_priority: Priority,

    // /// GPDMA interrupt priority.
    // ///
    // /// Defaults to P0 (highest).
    // #[cfg(gpdma)]
    // pub gpdma_interrupt_priority: Priority,
}


impl Default for Config {
    fn default() -> Self {
        Self {
            rcc: Default::default(),
            // #[cfg(dbgmcu)]
            // enable_debug_during_sleep: true,
            // #[cfg(any(stm32l4, stm32l5, stm32u5))]
            // enable_independent_io_supply: true,
            // #[cfg(bdma)]
            // bdma_interrupt_priority: Priority::P0,
            // #[cfg(dma)]
            // dma_interrupt_priority: Priority::P0,
            // #[cfg(gpdma)]
            // gpdma_interrupt_priority: Priority::P0,
        }
    }
}

/// Initialize the `embassy-stm32` HAL with the provided configuration.
///
/// This returns the peripheral singletons that can be used for creating drivers.
///
/// This should only be called once at startup, otherwise it panics.
pub fn init(config: Config) -> Peripherals {
    critical_section::with(|cs| {
        let p = Peripherals::take_with_cs(cs);
        unsafe {
            rcc::init(config.rcc);
            gpio::init(cs);

            #[cfg(feature = "_time-driver")]
            // must be after rcc init
            time_driver::init(cs);

            #[cfg(feature = "exti")]
            exti::init(cs);
        };
        p
    })
}


// This must go last, so that it sees all the impl_foo! macros defined earlier.
pub(crate) mod _generated {
    #![allow(dead_code)]
    #![allow(unused_imports)]
    #![allow(non_snake_case)]
    #![allow(missing_docs)]

    include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
}

pub use crate::_generated::interrupt;

pub use _generated::{peripherals, Peripherals};
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};


// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
    ($vis:vis struct $name:ident {
        $(
            $(#[cfg($cond_irq:meta)])?
            $irq:ident => $(
                $(#[cfg($cond_handler:meta)])?
                $handler:ty
            ),*;
        )*
    }) => {
        #[derive(Copy, Clone)]
        $vis struct $name;

        $(
            #[allow(non_snake_case)]
            #[no_mangle]
            $(#[cfg($cond_irq)])?
            unsafe extern "C" fn $irq() {
                $(
                    $(#[cfg($cond_handler)])?
                    <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();

                )*
            }
            $(#[cfg($cond_irq)])?
            $crate::bind_interrupts!(@inner
                $(
                    $(#[cfg($cond_handler)])?
                    unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
                )*
            );
        )*
    };
    (@inner $($t:tt)*) => {
        $($t)*
    }
}