| @@ -45,6 +45,79 @@ net = ["embassy-net", "vcell"] | |||||||
|  |  | ||||||
| # BEGIN GENERATED FEATURES | # BEGIN GENERATED FEATURES | ||||||
| # Generated by gen_features.py. DO NOT EDIT. | # Generated by gen_features.py. DO NOT EDIT. | ||||||
|  | stm32f030c6 = [ "stm32-metapac/stm32f030c6",] | ||||||
|  | stm32f030c8 = [ "stm32-metapac/stm32f030c8",] | ||||||
|  | stm32f030cc = [ "stm32-metapac/stm32f030cc",] | ||||||
|  | stm32f030f4 = [ "stm32-metapac/stm32f030f4",] | ||||||
|  | stm32f030k6 = [ "stm32-metapac/stm32f030k6",] | ||||||
|  | stm32f030r8 = [ "stm32-metapac/stm32f030r8",] | ||||||
|  | stm32f030rc = [ "stm32-metapac/stm32f030rc",] | ||||||
|  | stm32f031c4 = [ "stm32-metapac/stm32f031c4",] | ||||||
|  | stm32f031c6 = [ "stm32-metapac/stm32f031c6",] | ||||||
|  | stm32f031e6 = [ "stm32-metapac/stm32f031e6",] | ||||||
|  | stm32f031f4 = [ "stm32-metapac/stm32f031f4",] | ||||||
|  | stm32f031f6 = [ "stm32-metapac/stm32f031f6",] | ||||||
|  | stm32f031g4 = [ "stm32-metapac/stm32f031g4",] | ||||||
|  | stm32f031g6 = [ "stm32-metapac/stm32f031g6",] | ||||||
|  | stm32f031k4 = [ "stm32-metapac/stm32f031k4",] | ||||||
|  | stm32f031k6 = [ "stm32-metapac/stm32f031k6",] | ||||||
|  | stm32f038c6 = [ "stm32-metapac/stm32f038c6",] | ||||||
|  | stm32f038e6 = [ "stm32-metapac/stm32f038e6",] | ||||||
|  | stm32f038f6 = [ "stm32-metapac/stm32f038f6",] | ||||||
|  | stm32f038g6 = [ "stm32-metapac/stm32f038g6",] | ||||||
|  | stm32f038k6 = [ "stm32-metapac/stm32f038k6",] | ||||||
|  | stm32f042c4 = [ "stm32-metapac/stm32f042c4",] | ||||||
|  | stm32f042c6 = [ "stm32-metapac/stm32f042c6",] | ||||||
|  | stm32f042f4 = [ "stm32-metapac/stm32f042f4",] | ||||||
|  | stm32f042f6 = [ "stm32-metapac/stm32f042f6",] | ||||||
|  | stm32f042g4 = [ "stm32-metapac/stm32f042g4",] | ||||||
|  | stm32f042g6 = [ "stm32-metapac/stm32f042g6",] | ||||||
|  | stm32f042k4 = [ "stm32-metapac/stm32f042k4",] | ||||||
|  | stm32f042k6 = [ "stm32-metapac/stm32f042k6",] | ||||||
|  | stm32f042t6 = [ "stm32-metapac/stm32f042t6",] | ||||||
|  | stm32f048c6 = [ "stm32-metapac/stm32f048c6",] | ||||||
|  | stm32f048g6 = [ "stm32-metapac/stm32f048g6",] | ||||||
|  | stm32f048t6 = [ "stm32-metapac/stm32f048t6",] | ||||||
|  | stm32f051c4 = [ "stm32-metapac/stm32f051c4",] | ||||||
|  | stm32f051c6 = [ "stm32-metapac/stm32f051c6",] | ||||||
|  | stm32f051c8 = [ "stm32-metapac/stm32f051c8",] | ||||||
|  | stm32f051k4 = [ "stm32-metapac/stm32f051k4",] | ||||||
|  | stm32f051k6 = [ "stm32-metapac/stm32f051k6",] | ||||||
|  | stm32f051k8 = [ "stm32-metapac/stm32f051k8",] | ||||||
|  | stm32f051r4 = [ "stm32-metapac/stm32f051r4",] | ||||||
|  | stm32f051r6 = [ "stm32-metapac/stm32f051r6",] | ||||||
|  | stm32f051r8 = [ "stm32-metapac/stm32f051r8",] | ||||||
|  | stm32f051t8 = [ "stm32-metapac/stm32f051t8",] | ||||||
|  | stm32f058c8 = [ "stm32-metapac/stm32f058c8",] | ||||||
|  | stm32f058r8 = [ "stm32-metapac/stm32f058r8",] | ||||||
|  | stm32f058t8 = [ "stm32-metapac/stm32f058t8",] | ||||||
|  | stm32f070c6 = [ "stm32-metapac/stm32f070c6",] | ||||||
|  | stm32f070cb = [ "stm32-metapac/stm32f070cb",] | ||||||
|  | stm32f070f6 = [ "stm32-metapac/stm32f070f6",] | ||||||
|  | stm32f070rb = [ "stm32-metapac/stm32f070rb",] | ||||||
|  | stm32f071c8 = [ "stm32-metapac/stm32f071c8",] | ||||||
|  | stm32f071cb = [ "stm32-metapac/stm32f071cb",] | ||||||
|  | stm32f071rb = [ "stm32-metapac/stm32f071rb",] | ||||||
|  | stm32f071v8 = [ "stm32-metapac/stm32f071v8",] | ||||||
|  | stm32f071vb = [ "stm32-metapac/stm32f071vb",] | ||||||
|  | stm32f072c8 = [ "stm32-metapac/stm32f072c8",] | ||||||
|  | stm32f072cb = [ "stm32-metapac/stm32f072cb",] | ||||||
|  | stm32f072r8 = [ "stm32-metapac/stm32f072r8",] | ||||||
|  | stm32f072rb = [ "stm32-metapac/stm32f072rb",] | ||||||
|  | stm32f072v8 = [ "stm32-metapac/stm32f072v8",] | ||||||
|  | stm32f072vb = [ "stm32-metapac/stm32f072vb",] | ||||||
|  | stm32f078cb = [ "stm32-metapac/stm32f078cb",] | ||||||
|  | stm32f078rb = [ "stm32-metapac/stm32f078rb",] | ||||||
|  | stm32f078vb = [ "stm32-metapac/stm32f078vb",] | ||||||
|  | stm32f091cb = [ "stm32-metapac/stm32f091cb",] | ||||||
|  | stm32f091cc = [ "stm32-metapac/stm32f091cc",] | ||||||
|  | stm32f091rb = [ "stm32-metapac/stm32f091rb",] | ||||||
|  | stm32f091rc = [ "stm32-metapac/stm32f091rc",] | ||||||
|  | stm32f091vb = [ "stm32-metapac/stm32f091vb",] | ||||||
|  | stm32f091vc = [ "stm32-metapac/stm32f091vc",] | ||||||
|  | stm32f098cc = [ "stm32-metapac/stm32f098cc",] | ||||||
|  | stm32f098rc = [ "stm32-metapac/stm32f098rc",] | ||||||
|  | stm32f098vc = [ "stm32-metapac/stm32f098vc",] | ||||||
| stm32f401cb = [ "stm32-metapac/stm32f401cb",] | stm32f401cb = [ "stm32-metapac/stm32f401cb",] | ||||||
| stm32f401cc = [ "stm32-metapac/stm32f401cc",] | stm32f401cc = [ "stm32-metapac/stm32f401cc",] | ||||||
| stm32f401cd = [ "stm32-metapac/stm32f401cd",] | stm32f401cd = [ "stm32-metapac/stm32f401cd",] | ||||||
|   | |||||||
| @@ -33,10 +33,6 @@ if len(c) > 1: | |||||||
| with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f: | with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f: | ||||||
|     chip = yaml.load(f, Loader=SafeLoader) |     chip = yaml.load(f, Loader=SafeLoader) | ||||||
|  |  | ||||||
| # ======= load GPIO AF |  | ||||||
| with open(f'{data_path}/gpio_af/{chip["gpio_af"]}.yaml', 'r') as f: |  | ||||||
|     af = yaml.load(f, Loader=SafeLoader) |  | ||||||
|  |  | ||||||
| # ======= Generate! | # ======= Generate! | ||||||
| with open(output_file, 'w') as f: | with open(output_file, 'w') as f: | ||||||
|     singletons = []  # USART1, PA5, EXTI8 |     singletons = []  # USART1, PA5, EXTI8 | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ dname = os.path.dirname(abspath) | |||||||
| os.chdir(dname) | os.chdir(dname) | ||||||
|  |  | ||||||
| supported_families = [ | supported_families = [ | ||||||
|  |     "STM32F0", | ||||||
|     'STM32F4', |     'STM32F4', | ||||||
|     'STM32L0', |     'STM32L0', | ||||||
|     'STM32L4', |     'STM32L4', | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								embassy-stm32/src/exti/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								embassy-stm32/src/exti/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | #![macro_use] | ||||||
|  |  | ||||||
|  | macro_rules! foreach_exti_irq { | ||||||
|  |     ($action:ident) => { | ||||||
|  |         crate::pac::interrupts!( | ||||||
|  |             (EXTI0)  => { $action!(EXTI0); }; | ||||||
|  |             (EXTI1)  => { $action!(EXTI1); }; | ||||||
|  |             (EXTI2)  => { $action!(EXTI2); }; | ||||||
|  |             (EXTI3)  => { $action!(EXTI3); }; | ||||||
|  |             (EXTI4)  => { $action!(EXTI4); }; | ||||||
|  |             (EXTI5)  => { $action!(EXTI5); }; | ||||||
|  |             (EXTI6)  => { $action!(EXTI6); }; | ||||||
|  |             (EXTI7)  => { $action!(EXTI7); }; | ||||||
|  |             (EXTI8)  => { $action!(EXTI8); }; | ||||||
|  |             (EXTI9)  => { $action!(EXTI9); }; | ||||||
|  |             (EXTI10) => { $action!(EXTI10); }; | ||||||
|  |             (EXTI11) => { $action!(EXTI11); }; | ||||||
|  |             (EXTI12) => { $action!(EXTI12); }; | ||||||
|  |             (EXTI13) => { $action!(EXTI13); }; | ||||||
|  |             (EXTI14) => { $action!(EXTI14); }; | ||||||
|  |             (EXTI15) => { $action!(EXTI15); }; | ||||||
|  |  | ||||||
|  |             // plus the weird ones | ||||||
|  |             (EXTI0_1)   => { $action!( EXTI0_1 ); }; | ||||||
|  |             (EXTI15_10) => { $action!(EXTI15_10); }; | ||||||
|  |             (EXTI15_4)  => { $action!(EXTI15_4); }; | ||||||
|  |             (EXTI1_0)   => { $action!(EXTI1_0); }; | ||||||
|  |             (EXTI2_3)   => { $action!(EXTI2_3); }; | ||||||
|  |             (EXTI2_TSC) => { $action!(EXTI2_TSC); }; | ||||||
|  |             (EXTI3_2)   => { $action!(EXTI3_2); }; | ||||||
|  |             (EXTI4_15)  => { $action!(EXTI4_15); }; | ||||||
|  |             (EXTI9_5)   => { $action!(EXTI9_5); }; | ||||||
|  |         ); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg_attr(exti_v1, path = "v1.rs")] | ||||||
|  | #[cfg_attr(exti_wb55, path = "v2.rs")] | ||||||
|  | mod _version; | ||||||
|  |  | ||||||
|  | #[allow(unused)] | ||||||
|  | pub use _version::*; | ||||||
|  |  | ||||||
|  | use crate::peripherals; | ||||||
|  | use embassy_extras::unsafe_impl_unborrow; | ||||||
|  |  | ||||||
|  | pub(crate) mod sealed { | ||||||
|  |     pub trait Channel {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub trait Channel: sealed::Channel + Sized { | ||||||
|  |     fn number(&self) -> usize; | ||||||
|  |     fn degrade(self) -> AnyChannel { | ||||||
|  |         AnyChannel { | ||||||
|  |             number: self.number() as u8, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub struct AnyChannel { | ||||||
|  |     number: u8, | ||||||
|  | } | ||||||
|  | unsafe_impl_unborrow!(AnyChannel); | ||||||
|  | impl sealed::Channel for AnyChannel {} | ||||||
|  | impl Channel for AnyChannel { | ||||||
|  |     fn number(&self) -> usize { | ||||||
|  |         self.number as usize | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | macro_rules! impl_exti { | ||||||
|  |     ($type:ident, $number:expr) => { | ||||||
|  |         impl sealed::Channel for peripherals::$type {} | ||||||
|  |         impl Channel for peripherals::$type { | ||||||
|  |             fn number(&self) -> usize { | ||||||
|  |                 $number as usize | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl_exti!(EXTI0, 0); | ||||||
|  | impl_exti!(EXTI1, 1); | ||||||
|  | impl_exti!(EXTI2, 2); | ||||||
|  | impl_exti!(EXTI3, 3); | ||||||
|  | impl_exti!(EXTI4, 4); | ||||||
|  | impl_exti!(EXTI5, 5); | ||||||
|  | impl_exti!(EXTI6, 6); | ||||||
|  | impl_exti!(EXTI7, 7); | ||||||
|  | impl_exti!(EXTI8, 8); | ||||||
|  | impl_exti!(EXTI9, 9); | ||||||
|  | impl_exti!(EXTI10, 10); | ||||||
|  | impl_exti!(EXTI11, 11); | ||||||
|  | impl_exti!(EXTI12, 12); | ||||||
|  | impl_exti!(EXTI13, 13); | ||||||
|  | impl_exti!(EXTI14, 14); | ||||||
|  | impl_exti!(EXTI15, 15); | ||||||
|  |  | ||||||
|  | macro_rules! enable_irq { | ||||||
|  |     ($e:ident) => { | ||||||
|  |         crate::interrupt::$e::steal().enable(); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// safety: must be called only once | ||||||
|  | pub(crate) unsafe fn init() { | ||||||
|  |     use embassy::interrupt::Interrupt; | ||||||
|  |     use embassy::interrupt::InterruptExt; | ||||||
|  |  | ||||||
|  |     foreach_exti_irq!(enable_irq); | ||||||
|  | } | ||||||
| @@ -1,4 +1,3 @@ | |||||||
| #![macro_use] |  | ||||||
| use core::convert::Infallible; | use core::convert::Infallible; | ||||||
| use core::future::Future; | use core::future::Future; | ||||||
| use core::marker::PhantomData; | use core::marker::PhantomData; | ||||||
| @@ -6,14 +5,12 @@ use core::pin::Pin; | |||||||
| use core::task::{Context, Poll}; | use core::task::{Context, Poll}; | ||||||
| use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; | use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; | ||||||
| use embassy::util::{AtomicWaker, Unborrow}; | use embassy::util::{AtomicWaker, Unborrow}; | ||||||
| use embassy_extras::unsafe_impl_unborrow; |  | ||||||
| use embedded_hal::digital::v2::InputPin; | use embedded_hal::digital::v2::InputPin; | ||||||
| use pac::exti::{regs, vals}; | use pac::exti::{regs, vals}; | ||||||
| 
 | 
 | ||||||
| use crate::gpio::{AnyPin, Input, Pin as GpioPin}; | use crate::gpio::{AnyPin, Input, Pin as GpioPin}; | ||||||
| use crate::pac; | use crate::pac; | ||||||
| use crate::pac::{EXTI, SYSCFG}; | use crate::pac::{EXTI, SYSCFG}; | ||||||
| use crate::peripherals; |  | ||||||
| 
 | 
 | ||||||
| const EXTI_COUNT: usize = 16; | const EXTI_COUNT: usize = 16; | ||||||
| const NEW_AW: AtomicWaker = AtomicWaker::new(); | const NEW_AW: AtomicWaker = AtomicWaker::new(); | ||||||
| @@ -160,106 +157,6 @@ impl<'a> Future for ExtiInputFuture<'a> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub(crate) mod sealed { |  | ||||||
|     pub trait Channel {} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub trait Channel: sealed::Channel + Sized { |  | ||||||
|     fn number(&self) -> usize; |  | ||||||
|     fn degrade(self) -> AnyChannel { |  | ||||||
|         AnyChannel { |  | ||||||
|             number: self.number() as u8, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct AnyChannel { |  | ||||||
|     number: u8, |  | ||||||
| } |  | ||||||
| unsafe_impl_unborrow!(AnyChannel); |  | ||||||
| impl sealed::Channel for AnyChannel {} |  | ||||||
| impl Channel for AnyChannel { |  | ||||||
|     fn number(&self) -> usize { |  | ||||||
|         self.number as usize |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| macro_rules! impl_exti { |  | ||||||
|     ($type:ident, $number:expr) => { |  | ||||||
|         impl sealed::Channel for peripherals::$type {} |  | ||||||
|         impl Channel for peripherals::$type { |  | ||||||
|             fn number(&self) -> usize { |  | ||||||
|                 $number as usize |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl_exti!(EXTI0, 0); |  | ||||||
| impl_exti!(EXTI1, 1); |  | ||||||
| impl_exti!(EXTI2, 2); |  | ||||||
| impl_exti!(EXTI3, 3); |  | ||||||
| impl_exti!(EXTI4, 4); |  | ||||||
| impl_exti!(EXTI5, 5); |  | ||||||
| impl_exti!(EXTI6, 6); |  | ||||||
| impl_exti!(EXTI7, 7); |  | ||||||
| impl_exti!(EXTI8, 8); |  | ||||||
| impl_exti!(EXTI9, 9); |  | ||||||
| impl_exti!(EXTI10, 10); |  | ||||||
| impl_exti!(EXTI11, 11); |  | ||||||
| impl_exti!(EXTI12, 12); |  | ||||||
| impl_exti!(EXTI13, 13); |  | ||||||
| impl_exti!(EXTI14, 14); |  | ||||||
| impl_exti!(EXTI15, 15); |  | ||||||
| 
 |  | ||||||
| macro_rules! foreach_exti_irq { |  | ||||||
|     ($action:ident) => { |  | ||||||
|         crate::pac::interrupts!( |  | ||||||
|             (EXTI0)  => { $action!(EXTI0); }; |  | ||||||
|             (EXTI1)  => { $action!(EXTI1); }; |  | ||||||
|             (EXTI2)  => { $action!(EXTI2); }; |  | ||||||
|             (EXTI3)  => { $action!(EXTI3); }; |  | ||||||
|             (EXTI4)  => { $action!(EXTI4); }; |  | ||||||
|             (EXTI5)  => { $action!(EXTI5); }; |  | ||||||
|             (EXTI6)  => { $action!(EXTI6); }; |  | ||||||
|             (EXTI7)  => { $action!(EXTI7); }; |  | ||||||
|             (EXTI8)  => { $action!(EXTI8); }; |  | ||||||
|             (EXTI9)  => { $action!(EXTI9); }; |  | ||||||
|             (EXTI10) => { $action!(EXTI10); }; |  | ||||||
|             (EXTI11) => { $action!(EXTI11); }; |  | ||||||
|             (EXTI12) => { $action!(EXTI12); }; |  | ||||||
|             (EXTI13) => { $action!(EXTI13); }; |  | ||||||
|             (EXTI14) => { $action!(EXTI14); }; |  | ||||||
|             (EXTI15) => { $action!(EXTI15); }; |  | ||||||
| 
 |  | ||||||
|             // plus the weird ones
 |  | ||||||
|             (EXTI0_1)   => { $action!( EXTI0_1 ); }; |  | ||||||
|             (EXTI15_10) => { $action!(EXTI15_10); }; |  | ||||||
|             (EXTI15_4)  => { $action!(EXTI15_4); }; |  | ||||||
|             (EXTI1_0)   => { $action!(EXTI1_0); }; |  | ||||||
|             (EXTI2_3)   => { $action!(EXTI2_3); }; |  | ||||||
|             (EXTI2_TSC) => { $action!(EXTI2_TSC); }; |  | ||||||
|             (EXTI3_2)   => { $action!(EXTI3_2); }; |  | ||||||
|             (EXTI4_15)  => { $action!(EXTI4_15); }; |  | ||||||
|             (EXTI9_5)   => { $action!(EXTI9_5); }; |  | ||||||
|         ); |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| macro_rules! enable_irq { |  | ||||||
|     ($e:ident) => { |  | ||||||
|         crate::interrupt::$e::steal().enable(); |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// safety: must be called only once
 |  | ||||||
| pub(crate) unsafe fn init() { |  | ||||||
|     use embassy::interrupt::Interrupt; |  | ||||||
|     use embassy::interrupt::InterruptExt; |  | ||||||
| 
 |  | ||||||
|     foreach_exti_irq!(enable_irq); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| use crate::interrupt; | use crate::interrupt; | ||||||
| 
 | 
 | ||||||
| macro_rules! impl_irq { | macro_rules! impl_irq { | ||||||
							
								
								
									
										1
									
								
								embassy-stm32/src/exti/v2.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								embassy-stm32/src/exti/v2.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  |  | ||||||
| @@ -16,7 +16,6 @@ pub mod interrupt; | |||||||
| pub mod time; | pub mod time; | ||||||
|  |  | ||||||
| // Always-present hardware | // Always-present hardware | ||||||
| pub mod exti; |  | ||||||
| pub mod gpio; | pub mod gpio; | ||||||
| pub mod rcc; | pub mod rcc; | ||||||
|  |  | ||||||
| @@ -31,6 +30,8 @@ pub mod dac; | |||||||
| pub mod dma; | pub mod dma; | ||||||
| #[cfg(all(eth, feature = "net"))] | #[cfg(all(eth, feature = "net"))] | ||||||
| pub mod eth; | pub mod eth; | ||||||
|  | #[cfg(exti)] | ||||||
|  | pub mod exti; | ||||||
| #[cfg(i2c)] | #[cfg(i2c)] | ||||||
| pub mod i2c; | pub mod i2c; | ||||||
| #[cfg(pwr)] | #[cfg(pwr)] | ||||||
| @@ -83,10 +84,9 @@ pub fn init(config: Config) -> Peripherals { | |||||||
|     let p = Peripherals::take(); |     let p = Peripherals::take(); | ||||||
|  |  | ||||||
|     unsafe { |     unsafe { | ||||||
|         exti::init(); |  | ||||||
|  |  | ||||||
|         #[cfg(dma)] |         #[cfg(dma)] | ||||||
|         dma::init(); |         dma::init(); | ||||||
|  |         #[cfg(exti)] | ||||||
|         exti::init(); |         exti::init(); | ||||||
|         rcc::init(config.rcc); |         rcc::init(config.rcc); | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										231
									
								
								embassy-stm32/src/rcc/f0/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								embassy-stm32/src/rcc/f0/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | use core::marker::PhantomData; | ||||||
|  |  | ||||||
|  | use embassy::util::Unborrow; | ||||||
|  |  | ||||||
|  | use crate::pac::{DBGMCU, FLASH, RCC}; | ||||||
|  | use crate::peripherals; | ||||||
|  | use crate::time::Hertz; | ||||||
|  |  | ||||||
|  | use super::{set_freqs, Clocks}; | ||||||
|  |  | ||||||
|  | const HSI: u32 = 8_000_000; | ||||||
|  |  | ||||||
|  | /// Configuration of the clocks | ||||||
|  | /// | ||||||
|  | /// hse takes precedence over hsi48 if both are enabled | ||||||
|  | #[non_exhaustive] | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct Config { | ||||||
|  |     pub hse: Option<Hertz>, | ||||||
|  |     pub bypass_hse: bool, | ||||||
|  |     pub usb_pll: bool, | ||||||
|  |  | ||||||
|  |     #[cfg(rcc_f0)] | ||||||
|  |     pub hsi48: bool, | ||||||
|  |  | ||||||
|  |     pub sys_ck: Option<Hertz>, | ||||||
|  |     pub hclk: Option<Hertz>, | ||||||
|  |     pub pclk: Option<Hertz>, | ||||||
|  |     pub enable_debug_wfe: bool, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub struct Rcc<'d> { | ||||||
|  |     inner: PhantomData<&'d ()>, | ||||||
|  |     config: Config, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl<'d> Rcc<'d> { | ||||||
|  |     pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { | ||||||
|  |         Self { | ||||||
|  |             inner: PhantomData, | ||||||
|  |             config, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn freeze(self) -> Clocks { | ||||||
|  |         use crate::pac::rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Sw, Usbsw}; | ||||||
|  |  | ||||||
|  |         let sysclk = self.config.sys_ck.map(|v| v.0).unwrap_or(HSI); | ||||||
|  |  | ||||||
|  |         let (src_clk, use_hsi48) = self.config.hse.map(|v| (v.0, false)).unwrap_or_else(|| { | ||||||
|  |             #[cfg(rcc_f0)] | ||||||
|  |             if self.config.hsi48 { | ||||||
|  |                 return (48_000_000, true); | ||||||
|  |             } | ||||||
|  |             (HSI, false) | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         let (pllmul_bits, real_sysclk) = if sysclk == src_clk { | ||||||
|  |             (None, sysclk) | ||||||
|  |         } else { | ||||||
|  |             let prediv = if self.config.hse.is_some() { 1 } else { 2 }; | ||||||
|  |             let pllmul = (2 * prediv * sysclk + src_clk) / src_clk / 2; | ||||||
|  |             let pllmul = pllmul.max(2).min(16); | ||||||
|  |  | ||||||
|  |             let pllmul_bits = pllmul as u8 - 2; | ||||||
|  |             let real_sysclk = pllmul * src_clk / prediv; | ||||||
|  |             (Some(pllmul_bits), real_sysclk) | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         let hpre_bits = self | ||||||
|  |             .config | ||||||
|  |             .hclk | ||||||
|  |             .map(|hclk| match real_sysclk / hclk.0 { | ||||||
|  |                 0 => unreachable!(), | ||||||
|  |                 1 => 0b0111, | ||||||
|  |                 2 => 0b1000, | ||||||
|  |                 3..=5 => 0b1001, | ||||||
|  |                 6..=11 => 0b1010, | ||||||
|  |                 12..=39 => 0b1011, | ||||||
|  |                 40..=95 => 0b1100, | ||||||
|  |                 96..=191 => 0b1101, | ||||||
|  |                 192..=383 => 0b1110, | ||||||
|  |                 _ => 0b1111, | ||||||
|  |             }) | ||||||
|  |             .unwrap_or(0b0111); | ||||||
|  |         let hclk = real_sysclk / (1 << (hpre_bits - 0b0111)); | ||||||
|  |  | ||||||
|  |         let ppre_bits = self | ||||||
|  |             .config | ||||||
|  |             .pclk | ||||||
|  |             .map(|pclk| match hclk / pclk.0 { | ||||||
|  |                 0 => unreachable!(), | ||||||
|  |                 1 => 0b011, | ||||||
|  |                 2 => 0b100, | ||||||
|  |                 3..=5 => 0b101, | ||||||
|  |                 6..=11 => 0b110, | ||||||
|  |                 _ => 0b111, | ||||||
|  |             }) | ||||||
|  |             .unwrap_or(0b011); | ||||||
|  |  | ||||||
|  |         let ppre: u8 = 1 << (ppre_bits - 0b011); | ||||||
|  |         let pclk = hclk / u32::from(ppre); | ||||||
|  |  | ||||||
|  |         let timer_mul = if ppre == 1 { 1 } else { 2 }; | ||||||
|  |  | ||||||
|  |         // NOTE(safety) Atomic write | ||||||
|  |         unsafe { | ||||||
|  |             FLASH.acr().write(|w| { | ||||||
|  |                 let latency = if real_sysclk <= 24_000_000 { | ||||||
|  |                     0 | ||||||
|  |                 } else if real_sysclk <= 48_000_000 { | ||||||
|  |                     1 | ||||||
|  |                 } else { | ||||||
|  |                     2 | ||||||
|  |                 }; | ||||||
|  |                 w.latency().0 = latency; | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // NOTE(unsafe) We have exclusive access to the RCC | ||||||
|  |         unsafe { | ||||||
|  |             match (self.config.hse.is_some(), use_hsi48) { | ||||||
|  |                 (true, _) => { | ||||||
|  |                     RCC.cr().modify(|w| { | ||||||
|  |                         w.set_csson(true); | ||||||
|  |                         w.set_hseon(true); | ||||||
|  |  | ||||||
|  |                         if self.config.bypass_hse { | ||||||
|  |                             w.set_hsebyp(Hsebyp::BYPASSED); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                     while !RCC.cr().read().hserdy() {} | ||||||
|  |  | ||||||
|  |                     if pllmul_bits.is_some() { | ||||||
|  |                         RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSE_DIV_PREDIV)) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 (false, true) => { | ||||||
|  |                     // use_hsi48 will always be false for rcc_f0x0 | ||||||
|  |                     #[cfg(rcc_f0)] | ||||||
|  |                     RCC.cr2().modify(|w| w.set_hsi48on(true)); | ||||||
|  |                     #[cfg(rcc_f0)] | ||||||
|  |                     while !RCC.cr2().read().hsi48rdy() {} | ||||||
|  |  | ||||||
|  |                     #[cfg(rcc_f0)] | ||||||
|  |                     if pllmul_bits.is_some() { | ||||||
|  |                         RCC.cfgr() | ||||||
|  |                             .modify(|w| w.set_pllsrc(Pllsrc::HSI48_DIV_PREDIV)) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 _ => { | ||||||
|  |                     RCC.cr().modify(|w| w.set_hsion(true)); | ||||||
|  |                     while !RCC.cr().read().hsirdy() {} | ||||||
|  |  | ||||||
|  |                     if pllmul_bits.is_some() { | ||||||
|  |                         RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI_DIV2)) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if self.config.usb_pll { | ||||||
|  |                 RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLLCLK)); | ||||||
|  |             } | ||||||
|  |             // TODO: Option to use CRS (Clock Recovery) | ||||||
|  |  | ||||||
|  |             if let Some(pllmul_bits) = pllmul_bits { | ||||||
|  |                 RCC.cfgr().modify(|w| w.set_pllmul(Pllmul(pllmul_bits))); | ||||||
|  |  | ||||||
|  |                 RCC.cr().modify(|w| w.set_pllon(true)); | ||||||
|  |                 while !RCC.cr().read().pllrdy() {} | ||||||
|  |  | ||||||
|  |                 RCC.cfgr().modify(|w| { | ||||||
|  |                     w.set_ppre(Ppre(ppre_bits)); | ||||||
|  |                     w.set_hpre(Hpre(hpre_bits)); | ||||||
|  |                     w.set_sw(Sw::PLL) | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 RCC.cfgr().modify(|w| { | ||||||
|  |                     w.set_ppre(Ppre(ppre_bits)); | ||||||
|  |                     w.set_hpre(Hpre(hpre_bits)); | ||||||
|  |  | ||||||
|  |                     if self.config.hse.is_some() { | ||||||
|  |                         w.set_sw(Sw::HSE); | ||||||
|  |                     } else if use_hsi48 { | ||||||
|  |                         #[cfg(rcc_f0)] | ||||||
|  |                         w.set_sw(Sw::HSI48); | ||||||
|  |                     } else { | ||||||
|  |                         w.set_sw(Sw::HSI) | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if self.config.enable_debug_wfe { | ||||||
|  |                 RCC.ahbenr().modify(|w| w.set_dmaen(true)); | ||||||
|  |  | ||||||
|  |                 critical_section::with(|_| { | ||||||
|  |                     DBGMCU.cr().modify(|w| { | ||||||
|  |                         w.set_dbg_standby(true); | ||||||
|  |                         w.set_dbg_stop(true); | ||||||
|  |                     }); | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Clocks { | ||||||
|  |             sys: Hertz(real_sysclk), | ||||||
|  |             apb1: Hertz(pclk), | ||||||
|  |             apb1_tim: Hertz(pclk * timer_mul), | ||||||
|  |             apb2_tim: Hertz(0), | ||||||
|  |             ahb: Hertz(hclk), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub unsafe fn init(config: Config) { | ||||||
|  |     RCC.ahbenr().modify(|w| { | ||||||
|  |         w.set_iopaen(true); | ||||||
|  |         w.set_iopben(true); | ||||||
|  |         w.set_iopcen(true); | ||||||
|  |         w.set_iopden(true); | ||||||
|  |  | ||||||
|  |         #[cfg(rcc_f0)] | ||||||
|  |         w.set_iopeen(true); | ||||||
|  |  | ||||||
|  |         w.set_iopfen(true); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); | ||||||
|  |     let clocks = rcc.freeze(); | ||||||
|  |     set_freqs(clocks); | ||||||
|  | } | ||||||
| @@ -9,11 +9,14 @@ mod types; | |||||||
| pub struct Clocks { | pub struct Clocks { | ||||||
|     pub sys: Hertz, |     pub sys: Hertz, | ||||||
|     pub apb1: Hertz, |     pub apb1: Hertz, | ||||||
|  |  | ||||||
|  |     #[cfg(not(any(rcc_f0, rcc_f0x0)))] | ||||||
|     pub apb2: Hertz, |     pub apb2: Hertz, | ||||||
|  |  | ||||||
|     pub apb1_tim: Hertz, |     pub apb1_tim: Hertz, | ||||||
|     pub apb2_tim: Hertz, |     pub apb2_tim: Hertz, | ||||||
|  |  | ||||||
|     #[cfg(any(rcc_l0))] |     #[cfg(any(rcc_l0, rcc_f0, rcc_f0x0))] | ||||||
|     pub ahb: Hertz, |     pub ahb: Hertz, | ||||||
|  |  | ||||||
|     #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))] |     #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))] | ||||||
| @@ -65,6 +68,9 @@ cfg_if::cfg_if! { | |||||||
|     } else if #[cfg(rcc_wl5x)] { |     } else if #[cfg(rcc_wl5x)] { | ||||||
|         mod wl5x; |         mod wl5x; | ||||||
|         pub use wl5x::*; |         pub use wl5x::*; | ||||||
|  |     } else if #[cfg(any(rcc_f0, rcc_f0x0))] { | ||||||
|  |         mod f0; | ||||||
|  |         pub use f0::*; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
 Submodule stm32-data updated: 18f86c8312...eb76ee900a
									
								
							| @@ -19,7 +19,6 @@ pub struct Chip { | |||||||
|     pub cores: Vec<Core>, |     pub cores: Vec<Core>, | ||||||
|     pub flash: u32, |     pub flash: u32, | ||||||
|     pub ram: u32, |     pub ram: u32, | ||||||
|     pub gpio_af: String, |  | ||||||
|     pub packages: Vec<Package>, |     pub packages: Vec<Package>, | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user