diff options
Diffstat (limited to 'embassy-stm32/src/lib.rs')
| -rw-r--r-- | embassy-stm32/src/lib.rs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 95f59360a..8f001f03b 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -273,7 +273,123 @@ impl Default for Config { | |||
| 273 | /// This returns the peripheral singletons that can be used for creating drivers. | 273 | /// This returns the peripheral singletons that can be used for creating drivers. |
| 274 | /// | 274 | /// |
| 275 | /// This should only be called once at startup, otherwise it panics. | 275 | /// This should only be called once at startup, otherwise it panics. |
| 276 | #[cfg(not(feature = "_dual-core"))] | ||
| 276 | pub fn init(config: Config) -> Peripherals { | 277 | pub fn init(config: Config) -> Peripherals { |
| 278 | init_hw(config) | ||
| 279 | } | ||
| 280 | |||
| 281 | #[cfg(feature = "_dual-core")] | ||
| 282 | mod dual_core { | ||
| 283 | use rcc::Clocks; | ||
| 284 | |||
| 285 | use super::*; | ||
| 286 | use core::{ | ||
| 287 | mem::MaybeUninit, | ||
| 288 | sync::atomic::{AtomicUsize, Ordering}, | ||
| 289 | }; | ||
| 290 | |||
| 291 | /// Object containing data that embassy needs to share between cores. | ||
| 292 | /// | ||
| 293 | /// It cannot be initialized by the user. The intended use is: | ||
| 294 | /// | ||
| 295 | /// ``` | ||
| 296 | /// #[link_section = ".ram_d3"] | ||
| 297 | /// static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); | ||
| 298 | /// | ||
| 299 | /// init_secondary(&SHARED_DATA); | ||
| 300 | /// ``` | ||
| 301 | /// | ||
| 302 | /// This static must be placed in the same position for both cores. How and where this is done is left to the user. | ||
| 303 | pub struct SharedData { | ||
| 304 | init_flag: AtomicUsize, | ||
| 305 | clocks: MaybeUninit<Clocks>, | ||
| 306 | } | ||
| 307 | |||
| 308 | const INIT_DONE_FLAG: usize = 0xca11ab1e; | ||
| 309 | |||
| 310 | /// Initialize the `embassy-stm32` HAL with the provided configuration. | ||
| 311 | /// This function does the actual initialization of the hardware, in contrast to [init_secondary] or [try_init_secondary]. | ||
| 312 | /// Any core can do the init, but it's important only one core does it. | ||
| 313 | /// | ||
| 314 | /// This returns the peripheral singletons that can be used for creating drivers. | ||
| 315 | /// | ||
| 316 | /// This should only be called once at startup, otherwise it panics. | ||
| 317 | /// | ||
| 318 | /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs | ||
| 319 | /// for more information on its requirements. | ||
| 320 | pub fn init_primary(config: Config, shared_data: &'static MaybeUninit<SharedData>) -> Peripherals { | ||
| 321 | let shared_data = unsafe { shared_data.assume_init_ref() }; | ||
| 322 | |||
| 323 | rcc::set_freqs_ptr(&shared_data.clocks); | ||
| 324 | let p = init_hw(config); | ||
| 325 | |||
| 326 | shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst); | ||
| 327 | |||
| 328 | p | ||
| 329 | } | ||
| 330 | |||
| 331 | /// Try to initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary]. | ||
| 332 | /// | ||
| 333 | /// This returns the peripheral singletons that can be used for creating drivers if the other core is done with its init. | ||
| 334 | /// If the other core is not done yet, this will return `None`. | ||
| 335 | /// | ||
| 336 | /// This should only be called once at startup, otherwise it may panic. | ||
| 337 | /// | ||
| 338 | /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs | ||
| 339 | /// for more information on its requirements. | ||
| 340 | pub fn try_init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Option<Peripherals> { | ||
| 341 | let shared_data = unsafe { shared_data.assume_init_ref() }; | ||
| 342 | |||
| 343 | if shared_data | ||
| 344 | .init_flag | ||
| 345 | .compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst) | ||
| 346 | .is_err() | ||
| 347 | { | ||
| 348 | return None; | ||
| 349 | } | ||
| 350 | |||
| 351 | Some(init_secondary_hw(shared_data)) | ||
| 352 | } | ||
| 353 | |||
| 354 | /// Initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary]. | ||
| 355 | /// | ||
| 356 | /// This returns the peripheral singletons that can be used for creating drivers when the other core is done with its init. | ||
| 357 | /// If the other core is not done yet, this will spinloop wait on it. | ||
| 358 | /// | ||
| 359 | /// This should only be called once at startup, otherwise it may panic. | ||
| 360 | /// | ||
| 361 | /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs | ||
| 362 | /// for more information on its requirements. | ||
| 363 | pub fn init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Peripherals { | ||
| 364 | let shared_data = unsafe { shared_data.assume_init_ref() }; | ||
| 365 | |||
| 366 | while shared_data | ||
| 367 | .init_flag | ||
| 368 | .compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst) | ||
| 369 | .is_err() | ||
| 370 | {} | ||
| 371 | |||
| 372 | init_secondary_hw(shared_data) | ||
| 373 | } | ||
| 374 | |||
| 375 | fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals { | ||
| 376 | rcc::set_freqs_ptr(&shared_data.clocks); | ||
| 377 | |||
| 378 | // We use different timers on the different cores, so we have to still initialize one here | ||
| 379 | critical_section::with(|cs| { | ||
| 380 | // must be after rcc init | ||
| 381 | #[cfg(feature = "_time-driver")] | ||
| 382 | time_driver::init(cs); | ||
| 383 | }); | ||
| 384 | |||
| 385 | Peripherals::take() | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | #[cfg(feature = "_dual-core")] | ||
| 390 | pub use dual_core::*; | ||
| 391 | |||
| 392 | fn init_hw(config: Config) -> Peripherals { | ||
| 277 | critical_section::with(|cs| { | 393 | critical_section::with(|cs| { |
| 278 | let p = Peripherals::take_with_cs(cs); | 394 | let p = Peripherals::take_with_cs(cs); |
| 279 | 395 | ||
