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
/// Macro for creating a `std`-based bus manager with `'static` lifetime. /// /// This macro is a convenience helper for creating a bus manager that lives for the `'static` /// lifetime an thus can be safely shared across threads. /// /// This macro is only available with the `std` feature. /// /// # Syntax /// ```ignore /// let bus = shared_bus::new_std!(<Full Bus Type Signature> = <bus>).unwrap(); /// ``` /// /// The macro returns an Option which will be `Some(&'static bus_manager)` on the first run and /// `None` afterwards. This is necessary to uphold safety around the inner `static` variable. /// /// # Example /// ``` /// # struct MyDevice<T>(T); /// # impl<T> MyDevice<T> { /// # pub fn new(t: T) -> Self { MyDevice(t) } /// # pub fn do_something_on_the_bus(&mut self) { } /// # } /// # /// # struct SomeI2cBus; /// # let i2c = SomeI2cBus; /// // For example: /// // let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 90.khz(), clocks, &mut rcc.apb1); /// /// // The bus is a 'static reference -> it lives forever and references can be /// // shared with other threads. /// let bus: &'static _ = shared_bus::new_std!(SomeI2cBus = i2c).unwrap(); /// /// let mut proxy1 = bus.acquire_i2c(); /// let mut my_device = MyDevice::new(bus.acquire_i2c()); /// /// // We can easily move a proxy to another thread: /// # let t = /// std::thread::spawn(move || { /// my_device.do_something_on_the_bus(); /// }); /// # t.join().unwrap(); /// ``` #[cfg(feature = "std")] #[macro_export] macro_rules! new_std { ($bus_type:ty = $bus:expr) => {{ use $crate::once_cell::sync::OnceCell; static MANAGER: OnceCell<$crate::BusManagerStd<$bus_type>> = OnceCell::new(); let m = $crate::BusManagerStd::new($bus); match MANAGER.set(m) { Ok(_) => MANAGER.get(), Err(_) => None, } }}; } /// Macro for creating a Cortex-M bus manager with `'static` lifetime. /// /// This macro is a convenience helper for creating a bus manager that lives for the `'static` /// lifetime an thus can be safely shared across tasks/execution contexts (like interrupts). /// /// This macro is only available with the `cortex-m` feature. /// /// # Syntax /// ```ignore /// let bus = shared_bus::new_cortexm!(<Full Bus Type Signature> = <bus>).unwrap(); /// ``` /// /// The macro returns an Option which will be `Some(&'static bus_manager)` on the first run and /// `None` afterwards. This is necessary to uphold safety around the inner `static` variable. /// /// # Example /// ```no_run /// # use embedded_hal::blocking::i2c::Write; /// # struct MyDevice<T>(T); /// # impl<T> MyDevice<T> { /// # pub fn new(t: T) -> Self { MyDevice(t) } /// # pub fn do_something_on_the_bus(&mut self) { } /// # } /// # /// # struct SomeI2cBus; /// # impl Write for SomeI2cBus { /// # type Error = (); /// # fn write(&mut self, addr: u8, buffer: &[u8]) -> Result<(), Self::Error> { Ok(()) } /// # } /// static mut SHARED_DEVICE: /// Option<MyDevice<shared_bus::I2cProxy<shared_bus::CortexMMutex<SomeI2cBus>>>> /// = None; /// /// fn main() -> ! { /// # let i2c = SomeI2cBus; /// // For example: /// // let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 90.khz(), clocks, &mut rcc.apb1); /// /// // The bus is a 'static reference -> it lives forever and references can be /// // shared with other tasks. /// let bus: &'static _ = shared_bus::new_cortexm!(SomeI2cBus = i2c).unwrap(); /// /// let mut proxy1 = bus.acquire_i2c(); /// let my_device = MyDevice::new(bus.acquire_i2c()); /// /// unsafe { /// SHARED_DEVICE = Some(my_device); /// } /// /// cortex_m::asm::dmb(); /// /// // enable the interrupt /// /// loop { /// proxy1.write(0x39, &[0xaa]); /// } /// } /// /// fn INTERRUPT() { /// let dev = unsafe {SHARED_DEVICE.as_mut().unwrap()}; /// /// dev.do_something_on_the_bus(); /// } /// ``` #[cfg(feature = "cortex-m")] #[macro_export] macro_rules! new_cortexm { ($bus_type:ty = $bus:expr) => {{ let m: Option<&'static mut _> = $crate::cortex_m::singleton!( : $crate::BusManagerCortexM<$bus_type> = $crate::BusManagerCortexM::new($bus) ); m }}; } /// Construct a statically allocated bus manager. #[cfg(feature = "cortex-m")] #[macro_export] macro_rules! new_atomic_check { ($bus_type:ty = $bus:expr) => {{ let m: Option<&'static mut _> = $crate::cortex_m::singleton!( : $crate::BusManagerAtomicCheck<$bus_type> = $crate::BusManagerAtomicCheck::new($bus) ); m }}; }