diff options
| author | Ulf Lilleengen <[email protected]> | 2021-06-14 10:48:14 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2021-06-14 11:33:11 +0200 |
| commit | 95532726b2fe38c3510b8ba3e56c3cb8f4e3a914 (patch) | |
| tree | f201af1337a887cbb92220a25a18a34cad2c3313 | |
| parent | a13e07625fb191145d4dcb13b1dac9f4ef86bb8c (diff) | |
Add minimal RCC impls for L4 and F4
| -rw-r--r-- | embassy-stm32/src/rcc/f4/mod.rs | 204 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/h7/mod.rs | 26 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l0/mod.rs | 96 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l4/mod.rs | 203 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 54 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/spi.rs | 1 | ||||
| -rw-r--r-- | examples/stm32l0/src/bin/spi.rs | 1 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/spi.rs | 1 | ||||
| -rw-r--r-- | stm32-metapac/gen/src/lib.rs | 6 |
9 files changed, 455 insertions, 137 deletions
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs new file mode 100644 index 000000000..abd631944 --- /dev/null +++ b/embassy-stm32/src/rcc/f4/mod.rs | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | pub use super::common::*; | ||
| 2 | use crate::pac; | ||
| 3 | use crate::peripherals::{self, RCC}; | ||
| 4 | use crate::rcc::{get_freqs, set_freqs, Clocks}; | ||
| 5 | use crate::time::Hertz; | ||
| 6 | use crate::time::U32Ext; | ||
| 7 | use core::marker::PhantomData; | ||
| 8 | use embassy::util::Unborrow; | ||
| 9 | use embassy_extras::unborrow; | ||
| 10 | use pac::rcc::vals::{Hpre, Ppre, Sw}; | ||
| 11 | |||
| 12 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, | ||
| 13 | /// and with the addition of the init function to configure a system clock. | ||
| 14 | |||
| 15 | /// Only the basic setup using the HSE and HSI clocks are supported as of now. | ||
| 16 | |||
| 17 | /// HSI speed | ||
| 18 | pub const HSI_FREQ: u32 = 16_000_000; | ||
| 19 | |||
| 20 | /// System clock mux source | ||
| 21 | #[derive(Clone, Copy)] | ||
| 22 | pub enum ClockSrc { | ||
| 23 | HSE(Hertz), | ||
| 24 | HSI16, | ||
| 25 | } | ||
| 26 | |||
| 27 | impl Into<Ppre> for APBPrescaler { | ||
| 28 | fn into(self) -> Ppre { | ||
| 29 | match self { | ||
| 30 | APBPrescaler::NotDivided => Ppre::DIV1, | ||
| 31 | APBPrescaler::Div2 => Ppre::DIV2, | ||
| 32 | APBPrescaler::Div4 => Ppre::DIV4, | ||
| 33 | APBPrescaler::Div8 => Ppre::DIV8, | ||
| 34 | APBPrescaler::Div16 => Ppre::DIV16, | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | impl Into<Hpre> for AHBPrescaler { | ||
| 40 | fn into(self) -> Hpre { | ||
| 41 | match self { | ||
| 42 | AHBPrescaler::NotDivided => Hpre::DIV1, | ||
| 43 | AHBPrescaler::Div2 => Hpre::DIV2, | ||
| 44 | AHBPrescaler::Div4 => Hpre::DIV4, | ||
| 45 | AHBPrescaler::Div8 => Hpre::DIV8, | ||
| 46 | AHBPrescaler::Div16 => Hpre::DIV16, | ||
| 47 | AHBPrescaler::Div64 => Hpre::DIV64, | ||
| 48 | AHBPrescaler::Div128 => Hpre::DIV128, | ||
| 49 | AHBPrescaler::Div256 => Hpre::DIV256, | ||
| 50 | AHBPrescaler::Div512 => Hpre::DIV512, | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Clocks configutation | ||
| 56 | pub struct Config { | ||
| 57 | mux: ClockSrc, | ||
| 58 | ahb_pre: AHBPrescaler, | ||
| 59 | apb1_pre: APBPrescaler, | ||
| 60 | apb2_pre: APBPrescaler, | ||
| 61 | } | ||
| 62 | |||
| 63 | impl Default for Config { | ||
| 64 | #[inline] | ||
| 65 | fn default() -> Config { | ||
| 66 | Config { | ||
| 67 | mux: ClockSrc::HSI16, | ||
| 68 | ahb_pre: AHBPrescaler::NotDivided, | ||
| 69 | apb1_pre: APBPrescaler::NotDivided, | ||
| 70 | apb2_pre: APBPrescaler::NotDivided, | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | impl Config { | ||
| 76 | #[inline] | ||
| 77 | pub fn clock_src(mut self, mux: ClockSrc) -> Self { | ||
| 78 | self.mux = mux; | ||
| 79 | self | ||
| 80 | } | ||
| 81 | |||
| 82 | #[inline] | ||
| 83 | pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self { | ||
| 84 | self.ahb_pre = pre; | ||
| 85 | self | ||
| 86 | } | ||
| 87 | |||
| 88 | #[inline] | ||
| 89 | pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 90 | self.apb1_pre = pre; | ||
| 91 | self | ||
| 92 | } | ||
| 93 | |||
| 94 | #[inline] | ||
| 95 | pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 96 | self.apb2_pre = pre; | ||
| 97 | self | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | /// RCC peripheral | ||
| 102 | pub struct Rcc<'d> { | ||
| 103 | _rb: peripherals::RCC, | ||
| 104 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 105 | } | ||
| 106 | |||
| 107 | impl<'d> Rcc<'d> { | ||
| 108 | pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self { | ||
| 109 | unborrow!(rcc); | ||
| 110 | Self { | ||
| 111 | _rb: rcc, | ||
| 112 | phantom: PhantomData, | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | // Safety: RCC init must have been called | ||
| 117 | pub fn clocks(&self) -> &'static Clocks { | ||
| 118 | unsafe { get_freqs() } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration | ||
| 123 | pub trait RccExt { | ||
| 124 | fn freeze(self, config: Config) -> Clocks; | ||
| 125 | } | ||
| 126 | |||
| 127 | impl RccExt for RCC { | ||
| 128 | #[inline] | ||
| 129 | fn freeze(self, cfgr: Config) -> Clocks { | ||
| 130 | let rcc = pac::RCC; | ||
| 131 | let (sys_clk, sw) = match cfgr.mux { | ||
| 132 | ClockSrc::HSI16 => { | ||
| 133 | // Enable HSI16 | ||
| 134 | unsafe { | ||
| 135 | rcc.cr().write(|w| w.set_hsion(true)); | ||
| 136 | while !rcc.cr().read().hsirdy() {} | ||
| 137 | } | ||
| 138 | |||
| 139 | (HSI_FREQ, Sw::HSI) | ||
| 140 | } | ||
| 141 | ClockSrc::HSE(freq) => { | ||
| 142 | // Enable HSE | ||
| 143 | unsafe { | ||
| 144 | rcc.cr().write(|w| w.set_hseon(true)); | ||
| 145 | while !rcc.cr().read().hserdy() {} | ||
| 146 | } | ||
| 147 | |||
| 148 | (freq.0, Sw::HSE) | ||
| 149 | } | ||
| 150 | }; | ||
| 151 | |||
| 152 | unsafe { | ||
| 153 | rcc.cfgr().modify(|w| { | ||
| 154 | w.set_sw(sw.into()); | ||
| 155 | w.set_hpre(cfgr.ahb_pre.into()); | ||
| 156 | w.set_ppre1(cfgr.apb1_pre.into()); | ||
| 157 | w.set_ppre2(cfgr.apb2_pre.into()); | ||
| 158 | }); | ||
| 159 | } | ||
| 160 | |||
| 161 | let ahb_freq: u32 = match cfgr.ahb_pre { | ||
| 162 | AHBPrescaler::NotDivided => sys_clk, | ||
| 163 | pre => { | ||
| 164 | let pre: Hpre = pre.into(); | ||
| 165 | let pre = 1 << (pre.0 as u32 - 7); | ||
| 166 | sys_clk / pre | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | |||
| 170 | let apb1_freq = match cfgr.apb1_pre { | ||
| 171 | APBPrescaler::NotDivided => ahb_freq, | ||
| 172 | pre => { | ||
| 173 | let pre: Ppre = pre.into(); | ||
| 174 | let pre: u8 = 1 << (pre.0 - 3); | ||
| 175 | let freq = ahb_freq / pre as u32; | ||
| 176 | freq | ||
| 177 | } | ||
| 178 | }; | ||
| 179 | |||
| 180 | let apb2_freq = match cfgr.apb2_pre { | ||
| 181 | APBPrescaler::NotDivided => ahb_freq, | ||
| 182 | pre => { | ||
| 183 | let pre: Ppre = pre.into(); | ||
| 184 | let pre: u8 = 1 << (pre.0 - 3); | ||
| 185 | let freq = ahb_freq / (1 << (pre as u8 - 3)); | ||
| 186 | freq | ||
| 187 | } | ||
| 188 | }; | ||
| 189 | |||
| 190 | Clocks { | ||
| 191 | sys: sys_clk.hz(), | ||
| 192 | ahb1: ahb_freq.hz(), | ||
| 193 | ahb2: ahb_freq.hz(), | ||
| 194 | apb1: apb1_freq.hz(), | ||
| 195 | apb2: apb2_freq.hz(), | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | pub unsafe fn init(config: Config) { | ||
| 201 | let r = <peripherals::RCC as embassy::util::Steal>::steal(); | ||
| 202 | let clocks = r.freeze(config); | ||
| 203 | set_freqs(clocks); | ||
| 204 | } | ||
diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs index 11f8ec898..f51ea9d71 100644 --- a/embassy-stm32/src/rcc/h7/mod.rs +++ b/embassy-stm32/src/rcc/h7/mod.rs | |||
| @@ -6,22 +6,13 @@ use crate::pac::rcc::vals::Timpre; | |||
| 6 | use crate::pac::{DBGMCU, RCC, SYSCFG}; | 6 | use crate::pac::{DBGMCU, RCC, SYSCFG}; |
| 7 | use crate::peripherals; | 7 | use crate::peripherals; |
| 8 | use crate::pwr::{Power, VoltageScale}; | 8 | use crate::pwr::{Power, VoltageScale}; |
| 9 | use crate::rcc::{set_freqs, Clocks}; | ||
| 9 | use crate::time::Hertz; | 10 | use crate::time::Hertz; |
| 10 | 11 | ||
| 11 | mod pll; | 12 | mod pll; |
| 12 | use pll::pll_setup; | 13 | use pll::pll_setup; |
| 13 | pub use pll::PllConfig; | 14 | pub use pll::PllConfig; |
| 14 | 15 | ||
| 15 | // Clock type used by peripherals | ||
| 16 | #[derive(Clone, Copy)] | ||
| 17 | pub struct Clocks { | ||
| 18 | pub apb1: Hertz, | ||
| 19 | pub apb2: Hertz, | ||
| 20 | pub apb4: Hertz, | ||
| 21 | pub ahb2: Hertz, | ||
| 22 | pub c1: Hertz, | ||
| 23 | } | ||
| 24 | |||
| 25 | const HSI: Hertz = Hertz(64_000_000); | 16 | const HSI: Hertz = Hertz(64_000_000); |
| 26 | const CSI: Hertz = Hertz(4_000_000); | 17 | const CSI: Hertz = Hertz(4_000_000); |
| 27 | const HSI48: Hertz = Hertz(48_000_000); | 18 | const HSI48: Hertz = Hertz(48_000_000); |
| @@ -532,5 +523,16 @@ impl<'d> Rcc<'d> { | |||
| 532 | } | 523 | } |
| 533 | } | 524 | } |
| 534 | 525 | ||
| 535 | // TODO | 526 | pub unsafe fn init(config: Config) { |
| 536 | pub unsafe fn init(_config: Config) {} | 527 | let mut power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal(), false); |
| 528 | let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); | ||
| 529 | let core_clocks = rcc.freeze(&mut power); | ||
| 530 | set_freqs(Clocks { | ||
| 531 | sys: core_clocks.c_ck, | ||
| 532 | ahb1: core_clocks.hclk, | ||
| 533 | ahb2: core_clocks.hclk, | ||
| 534 | apb1: core_clocks.pclk1, | ||
| 535 | apb2: core_clocks.pclk2, | ||
| 536 | apb4: core_clocks.pclk4, | ||
| 537 | }); | ||
| 538 | } | ||
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index fc8a94883..8f056d51c 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | pub use super::common::*; | ||
| 1 | use crate::pac; | 2 | use crate::pac; |
| 2 | use crate::peripherals::{self, CRS, RCC, SYSCFG}; | 3 | use crate::peripherals::{self, CRS, RCC, SYSCFG}; |
| 3 | use crate::rcc::{get_freqs, set_freqs}; | 4 | use crate::rcc::{get_freqs, set_freqs, Clocks}; |
| 4 | use crate::time::Hertz; | 5 | use crate::time::Hertz; |
| 5 | use crate::time::U32Ext; | 6 | use crate::time::U32Ext; |
| 6 | use core::marker::PhantomData; | 7 | use core::marker::PhantomData; |
| @@ -12,13 +13,8 @@ use pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; | |||
| 12 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, | 13 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, |
| 13 | /// and with the addition of the init function to configure a system clock. | 14 | /// and with the addition of the init function to configure a system clock. |
| 14 | 15 | ||
| 15 | #[derive(Clone, Copy)] | 16 | /// HSI speed |
| 16 | pub struct Clocks { | 17 | pub const HSI_FREQ: u32 = 16_000_000; |
| 17 | pub sys: Hertz, | ||
| 18 | pub ahb: Hertz, | ||
| 19 | pub apb1: Hertz, | ||
| 20 | pub apb2: Hertz, | ||
| 21 | } | ||
| 22 | 18 | ||
| 23 | /// System clock mux source | 19 | /// System clock mux source |
| 24 | #[derive(Clone, Copy)] | 20 | #[derive(Clone, Copy)] |
| @@ -29,90 +25,6 @@ pub enum ClockSrc { | |||
| 29 | HSI16, | 25 | HSI16, |
| 30 | } | 26 | } |
| 31 | 27 | ||
| 32 | /// MSI Clock Range | ||
| 33 | /// | ||
| 34 | /// These ranges control the frequency of the MSI. Internally, these ranges map | ||
| 35 | /// to the `MSIRANGE` bits in the `RCC_ICSCR` register. | ||
| 36 | #[derive(Clone, Copy)] | ||
| 37 | pub enum MSIRange { | ||
| 38 | /// Around 65.536 kHz | ||
| 39 | Range0, | ||
| 40 | /// Around 131.072 kHz | ||
| 41 | Range1, | ||
| 42 | /// Around 262.144 kHz | ||
| 43 | Range2, | ||
| 44 | /// Around 524.288 kHz | ||
| 45 | Range3, | ||
| 46 | /// Around 1.048 MHz | ||
| 47 | Range4, | ||
| 48 | /// Around 2.097 MHz (reset value) | ||
| 49 | Range5, | ||
| 50 | /// Around 4.194 MHz | ||
| 51 | Range6, | ||
| 52 | } | ||
| 53 | |||
| 54 | impl Default for MSIRange { | ||
| 55 | fn default() -> MSIRange { | ||
| 56 | MSIRange::Range5 | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | /// PLL divider | ||
| 61 | #[derive(Clone, Copy)] | ||
| 62 | pub enum PLLDiv { | ||
| 63 | Div2, | ||
| 64 | Div3, | ||
| 65 | Div4, | ||
| 66 | } | ||
| 67 | |||
| 68 | /// PLL multiplier | ||
| 69 | #[derive(Clone, Copy)] | ||
| 70 | pub enum PLLMul { | ||
| 71 | Mul3, | ||
| 72 | Mul4, | ||
| 73 | Mul6, | ||
| 74 | Mul8, | ||
| 75 | Mul12, | ||
| 76 | Mul16, | ||
| 77 | Mul24, | ||
| 78 | Mul32, | ||
| 79 | Mul48, | ||
| 80 | } | ||
| 81 | |||
| 82 | /// AHB prescaler | ||
| 83 | #[derive(Clone, Copy)] | ||
| 84 | pub enum AHBPrescaler { | ||
| 85 | NotDivided, | ||
| 86 | Div2, | ||
| 87 | Div4, | ||
| 88 | Div8, | ||
| 89 | Div16, | ||
| 90 | Div64, | ||
| 91 | Div128, | ||
| 92 | Div256, | ||
| 93 | Div512, | ||
| 94 | } | ||
| 95 | |||
| 96 | /// APB prescaler | ||
| 97 | #[derive(Clone, Copy)] | ||
| 98 | pub enum APBPrescaler { | ||
| 99 | NotDivided, | ||
| 100 | Div2, | ||
| 101 | Div4, | ||
| 102 | Div8, | ||
| 103 | Div16, | ||
| 104 | } | ||
| 105 | |||
| 106 | /// PLL clock input source | ||
| 107 | #[derive(Clone, Copy)] | ||
| 108 | pub enum PLLSource { | ||
| 109 | HSI16, | ||
| 110 | HSE(Hertz), | ||
| 111 | } | ||
| 112 | |||
| 113 | /// HSI speed | ||
| 114 | pub const HSI_FREQ: u32 = 16_000_000; | ||
| 115 | |||
| 116 | impl Into<Pllmul> for PLLMul { | 28 | impl Into<Pllmul> for PLLMul { |
| 117 | fn into(self) -> Pllmul { | 29 | fn into(self) -> Pllmul { |
| 118 | match self { | 30 | match self { |
diff --git a/embassy-stm32/src/rcc/l4/mod.rs b/embassy-stm32/src/rcc/l4/mod.rs new file mode 100644 index 000000000..e8c488e06 --- /dev/null +++ b/embassy-stm32/src/rcc/l4/mod.rs | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | pub use super::common::*; | ||
| 2 | use crate::pac; | ||
| 3 | use crate::peripherals::{self, RCC}; | ||
| 4 | use crate::rcc::{get_freqs, set_freqs, Clocks}; | ||
| 5 | use crate::time::Hertz; | ||
| 6 | use crate::time::U32Ext; | ||
| 7 | use core::marker::PhantomData; | ||
| 8 | use embassy::util::Unborrow; | ||
| 9 | use embassy_extras::unborrow; | ||
| 10 | |||
| 11 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, | ||
| 12 | /// and with the addition of the init function to configure a system clock. | ||
| 13 | |||
| 14 | /// Only the basic setup using the HSE and HSI clocks are supported as of now. | ||
| 15 | |||
| 16 | /// HSI speed | ||
| 17 | pub const HSI_FREQ: u32 = 16_000_000; | ||
| 18 | |||
| 19 | /// System clock mux source | ||
| 20 | #[derive(Clone, Copy)] | ||
| 21 | pub enum ClockSrc { | ||
| 22 | HSE(Hertz), | ||
| 23 | HSI16, | ||
| 24 | } | ||
| 25 | |||
| 26 | impl Into<u8> for APBPrescaler { | ||
| 27 | fn into(self) -> u8 { | ||
| 28 | match self { | ||
| 29 | APBPrescaler::NotDivided => 1, | ||
| 30 | APBPrescaler::Div2 => 0x04, | ||
| 31 | APBPrescaler::Div4 => 0x05, | ||
| 32 | APBPrescaler::Div8 => 0x06, | ||
| 33 | APBPrescaler::Div16 => 0x07, | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | impl Into<u8> for AHBPrescaler { | ||
| 39 | fn into(self) -> u8 { | ||
| 40 | match self { | ||
| 41 | AHBPrescaler::NotDivided => 1, | ||
| 42 | AHBPrescaler::Div2 => 0x08, | ||
| 43 | AHBPrescaler::Div4 => 0x09, | ||
| 44 | AHBPrescaler::Div8 => 0x0a, | ||
| 45 | AHBPrescaler::Div16 => 0x0b, | ||
| 46 | AHBPrescaler::Div64 => 0x0c, | ||
| 47 | AHBPrescaler::Div128 => 0x0d, | ||
| 48 | AHBPrescaler::Div256 => 0x0e, | ||
| 49 | AHBPrescaler::Div512 => 0x0f, | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /// Clocks configutation | ||
| 55 | pub struct Config { | ||
| 56 | mux: ClockSrc, | ||
| 57 | ahb_pre: AHBPrescaler, | ||
| 58 | apb1_pre: APBPrescaler, | ||
| 59 | apb2_pre: APBPrescaler, | ||
| 60 | } | ||
| 61 | |||
| 62 | impl Default for Config { | ||
| 63 | #[inline] | ||
| 64 | fn default() -> Config { | ||
| 65 | Config { | ||
| 66 | mux: ClockSrc::HSI16, | ||
| 67 | ahb_pre: AHBPrescaler::NotDivided, | ||
| 68 | apb1_pre: APBPrescaler::NotDivided, | ||
| 69 | apb2_pre: APBPrescaler::NotDivided, | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | impl Config { | ||
| 75 | #[inline] | ||
| 76 | pub fn clock_src(mut self, mux: ClockSrc) -> Self { | ||
| 77 | self.mux = mux; | ||
| 78 | self | ||
| 79 | } | ||
| 80 | |||
| 81 | #[inline] | ||
| 82 | pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self { | ||
| 83 | self.ahb_pre = pre; | ||
| 84 | self | ||
| 85 | } | ||
| 86 | |||
| 87 | #[inline] | ||
| 88 | pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 89 | self.apb1_pre = pre; | ||
| 90 | self | ||
| 91 | } | ||
| 92 | |||
| 93 | #[inline] | ||
| 94 | pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 95 | self.apb2_pre = pre; | ||
| 96 | self | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | /// RCC peripheral | ||
| 101 | pub struct Rcc<'d> { | ||
| 102 | _rb: peripherals::RCC, | ||
| 103 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 104 | } | ||
| 105 | |||
| 106 | impl<'d> Rcc<'d> { | ||
| 107 | pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self { | ||
| 108 | unborrow!(rcc); | ||
| 109 | Self { | ||
| 110 | _rb: rcc, | ||
| 111 | phantom: PhantomData, | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | // Safety: RCC init must have been called | ||
| 116 | pub fn clocks(&self) -> &'static Clocks { | ||
| 117 | unsafe { get_freqs() } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration | ||
| 122 | pub trait RccExt { | ||
| 123 | fn freeze(self, config: Config) -> Clocks; | ||
| 124 | } | ||
| 125 | |||
| 126 | impl RccExt for RCC { | ||
| 127 | #[inline] | ||
| 128 | fn freeze(self, cfgr: Config) -> Clocks { | ||
| 129 | let rcc = pac::RCC; | ||
| 130 | let (sys_clk, sw) = match cfgr.mux { | ||
| 131 | ClockSrc::HSI16 => { | ||
| 132 | // Enable HSI16 | ||
| 133 | unsafe { | ||
| 134 | rcc.cr().write(|w| w.set_hsion(true)); | ||
| 135 | while !rcc.cr().read().hsirdy() {} | ||
| 136 | } | ||
| 137 | |||
| 138 | (HSI_FREQ, 0x01) | ||
| 139 | } | ||
| 140 | ClockSrc::HSE(freq) => { | ||
| 141 | // Enable HSE | ||
| 142 | unsafe { | ||
| 143 | rcc.cr().write(|w| w.set_hseon(true)); | ||
| 144 | while !rcc.cr().read().hserdy() {} | ||
| 145 | } | ||
| 146 | |||
| 147 | (freq.0, 0x02) | ||
| 148 | } | ||
| 149 | }; | ||
| 150 | |||
| 151 | unsafe { | ||
| 152 | rcc.cfgr().modify(|w| { | ||
| 153 | w.set_sw(sw.into()); | ||
| 154 | w.set_hpre(cfgr.ahb_pre.into()); | ||
| 155 | w.set_ppre1(cfgr.apb1_pre.into()); | ||
| 156 | w.set_ppre2(cfgr.apb2_pre.into()); | ||
| 157 | }); | ||
| 158 | } | ||
| 159 | |||
| 160 | let ahb_freq: u32 = match cfgr.ahb_pre { | ||
| 161 | AHBPrescaler::NotDivided => sys_clk, | ||
| 162 | pre => { | ||
| 163 | let pre: u8 = pre.into(); | ||
| 164 | let pre = 1 << (pre as u32 - 7); | ||
| 165 | sys_clk / pre | ||
| 166 | } | ||
| 167 | }; | ||
| 168 | |||
| 169 | let apb1_freq = match cfgr.apb1_pre { | ||
| 170 | APBPrescaler::NotDivided => ahb_freq, | ||
| 171 | pre => { | ||
| 172 | let pre: u8 = pre.into(); | ||
| 173 | let pre: u8 = 1 << (pre - 3); | ||
| 174 | let freq = ahb_freq / pre as u32; | ||
| 175 | freq | ||
| 176 | } | ||
| 177 | }; | ||
| 178 | |||
| 179 | let apb2_freq = match cfgr.apb2_pre { | ||
| 180 | APBPrescaler::NotDivided => ahb_freq, | ||
| 181 | pre => { | ||
| 182 | let pre: u8 = pre.into(); | ||
| 183 | let pre: u8 = 1 << (pre - 3); | ||
| 184 | let freq = ahb_freq / (1 << (pre as u8 - 3)); | ||
| 185 | freq | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | |||
| 189 | Clocks { | ||
| 190 | sys: sys_clk.hz(), | ||
| 191 | ahb1: ahb_freq.hz(), | ||
| 192 | ahb2: ahb_freq.hz(), | ||
| 193 | apb1: apb1_freq.hz(), | ||
| 194 | apb2: apb2_freq.hz(), | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | pub unsafe fn init(config: Config) { | ||
| 200 | let r = <peripherals::RCC as embassy::util::Steal>::steal(); | ||
| 201 | let clocks = r.freeze(config); | ||
| 202 | set_freqs(clocks); | ||
| 203 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 7271030aa..b5ca7f40a 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -1,7 +1,28 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use crate::peripherals; | 3 | use crate::peripherals; |
| 4 | use crate::time::Hertz; | ||
| 4 | use core::mem::MaybeUninit; | 5 | use core::mem::MaybeUninit; |
| 6 | mod common; | ||
| 7 | |||
| 8 | #[derive(Clone, Copy)] | ||
| 9 | pub struct Clocks { | ||
| 10 | pub sys: Hertz, | ||
| 11 | pub apb1: Hertz, | ||
| 12 | pub apb2: Hertz, | ||
| 13 | |||
| 14 | #[cfg(any(rcc_l0))] | ||
| 15 | pub ahb: Hertz, | ||
| 16 | |||
| 17 | #[cfg(any(rcc_l4, rcc_f4, rcc_h7))] | ||
| 18 | pub ahb1: Hertz, | ||
| 19 | |||
| 20 | #[cfg(any(rcc_l4, rcc_f4, rcc_h7))] | ||
| 21 | pub ahb2: Hertz, | ||
| 22 | |||
| 23 | #[cfg(any(rcc_h7))] | ||
| 24 | pub apb4: Hertz, | ||
| 25 | } | ||
| 5 | 26 | ||
| 6 | /// Frozen clock frequencies | 27 | /// Frozen clock frequencies |
| 7 | /// | 28 | /// |
| @@ -28,36 +49,11 @@ cfg_if::cfg_if! { | |||
| 28 | mod l0; | 49 | mod l0; |
| 29 | pub use l0::*; | 50 | pub use l0::*; |
| 30 | } else if #[cfg(rcc_l4)] { | 51 | } else if #[cfg(rcc_l4)] { |
| 31 | // TODO: Implement | 52 | mod l4; |
| 32 | use crate::time::Hertz; | 53 | pub use l4::*; |
| 33 | |||
| 34 | #[derive(Clone, Copy)] | ||
| 35 | pub struct Clocks { | ||
| 36 | pub apb1: Hertz, | ||
| 37 | pub apb2: Hertz, | ||
| 38 | pub ahb2: Hertz, | ||
| 39 | } | ||
| 40 | |||
| 41 | #[derive(Default)] | ||
| 42 | pub struct Config {} | ||
| 43 | pub unsafe fn init(_config: Config) { | ||
| 44 | } | ||
| 45 | } else if #[cfg(rcc_f4)] { | 54 | } else if #[cfg(rcc_f4)] { |
| 46 | // TODO: Implement | 55 | mod f4; |
| 47 | use crate::time::Hertz; | 56 | pub use f4::*; |
| 48 | |||
| 49 | #[derive(Clone, Copy)] | ||
| 50 | pub struct Clocks { | ||
| 51 | pub apb1: Hertz, | ||
| 52 | pub apb2: Hertz, | ||
| 53 | pub ahb2: Hertz, | ||
| 54 | } | ||
| 55 | |||
| 56 | #[derive(Default)] | ||
| 57 | pub struct Config {} | ||
| 58 | pub unsafe fn init(_config: Config) { | ||
| 59 | } | ||
| 60 | |||
| 61 | } else { | 57 | } else { |
| 62 | #[derive(Default)] | 58 | #[derive(Default)] |
| 63 | pub struct Config {} | 59 | pub struct Config {} |
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs index af0d57412..610bb64e9 100644 --- a/examples/stm32f4/src/bin/spi.rs +++ b/examples/stm32f4/src/bin/spi.rs | |||
| @@ -50,7 +50,6 @@ fn main() -> ! { | |||
| 50 | let p = embassy_stm32::init(Default::default()); | 50 | let p = embassy_stm32::init(Default::default()); |
| 51 | 51 | ||
| 52 | let mut spi = Spi::new( | 52 | let mut spi = Spi::new( |
| 53 | Hertz(16_000_000), | ||
| 54 | p.SPI3, | 53 | p.SPI3, |
| 55 | p.PC10, | 54 | p.PC10, |
| 56 | p.PC12, | 55 | p.PC12, |
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs index 4eb9bfdd2..0e828c436 100644 --- a/examples/stm32l0/src/bin/spi.rs +++ b/examples/stm32l0/src/bin/spi.rs | |||
| @@ -28,7 +28,6 @@ fn main() -> ! { | |||
| 28 | rcc.enable_debug_wfe(&mut p.DBGMCU, true); | 28 | rcc.enable_debug_wfe(&mut p.DBGMCU, true); |
| 29 | 29 | ||
| 30 | let mut spi = Spi::new( | 30 | let mut spi = Spi::new( |
| 31 | Hertz(16_000_000), | ||
| 32 | p.SPI1, | 31 | p.SPI1, |
| 33 | p.PB3, | 32 | p.PB3, |
| 34 | p.PA7, | 33 | p.PA7, |
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs index 9db854dc3..7c672b70d 100644 --- a/examples/stm32l4/src/bin/spi.rs +++ b/examples/stm32l4/src/bin/spi.rs | |||
| @@ -44,7 +44,6 @@ fn main() -> ! { | |||
| 44 | let p = embassy_stm32::init(Default::default()); | 44 | let p = embassy_stm32::init(Default::default()); |
| 45 | 45 | ||
| 46 | let mut spi = Spi::new( | 46 | let mut spi = Spi::new( |
| 47 | Hertz(16_000_000), | ||
| 48 | p.SPI3, | 47 | p.SPI3, |
| 49 | p.PC10, | 48 | p.PC10, |
| 50 | p.PC12, | 49 | p.PC12, |
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index ae01f1e85..eab4ebe23 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs | |||
| @@ -84,7 +84,11 @@ fn find_reg_for_field<'c>( | |||
| 84 | field_name: &str, | 84 | field_name: &str, |
| 85 | ) -> Option<(&'c str, &'c str)> { | 85 | ) -> Option<(&'c str, &'c str)> { |
| 86 | rcc.fieldsets.iter().find_map(|(name, fieldset)| { | 86 | rcc.fieldsets.iter().find_map(|(name, fieldset)| { |
| 87 | if name.starts_with(reg_prefix) { | 87 | // Workaround for some families that prefix register aliases with C1_, which does |
| 88 | // not help matching for clock name. | ||
| 89 | if name.starts_with("C1") { | ||
| 90 | None | ||
| 91 | } else if name.starts_with(reg_prefix) { | ||
| 88 | fieldset | 92 | fieldset |
| 89 | .fields | 93 | .fields |
| 90 | .iter() | 94 | .iter() |
