diff options
| -rwxr-xr-x | ci.sh | 1 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 69 | ||||
| -rw-r--r-- | embassy-stm32/src/pwr/f3.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/pwr/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f3/mod.rs | 374 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 5 | ||||
| -rw-r--r-- | examples/stm32f3/.cargo/config.toml | 6 | ||||
| -rw-r--r-- | examples/stm32f3/Cargo.toml | 22 | ||||
| -rw-r--r-- | examples/stm32f3/build.rs | 5 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/blinky.rs | 30 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/button.rs | 33 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/button_exti.rs | 29 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/hello.rs | 28 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/spi_dma.rs | 41 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/usart_dma.rs | 30 | ||||
| -rw-r--r-- | examples/stm32f3/src/example_common.rs | 19 | ||||
| m--------- | stm32-data | 0 | ||||
| -rw-r--r-- | stm32-gen-features/src/lib.rs | 1 |
18 files changed, 694 insertions, 1 deletions
| @@ -54,6 +54,7 @@ cargo batch \ | |||
| 54 | --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ | 54 | --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ |
| 55 | --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ | 55 | --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ |
| 56 | --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ | 56 | --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ |
| 57 | --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \ | ||
| 57 | --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ | 58 | --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ |
| 58 | --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ | 59 | --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ |
| 59 | --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32g0 \ | 60 | --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32g0 \ |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 74903de0b..135f9a918 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -223,6 +223,75 @@ stm32f107rb = [ "stm32-metapac/stm32f107rb" ] | |||
| 223 | stm32f107rc = [ "stm32-metapac/stm32f107rc" ] | 223 | stm32f107rc = [ "stm32-metapac/stm32f107rc" ] |
| 224 | stm32f107vb = [ "stm32-metapac/stm32f107vb" ] | 224 | stm32f107vb = [ "stm32-metapac/stm32f107vb" ] |
| 225 | stm32f107vc = [ "stm32-metapac/stm32f107vc" ] | 225 | stm32f107vc = [ "stm32-metapac/stm32f107vc" ] |
| 226 | stm32f301c6 = [ "stm32-metapac/stm32f301c6" ] | ||
| 227 | stm32f301c8 = [ "stm32-metapac/stm32f301c8" ] | ||
| 228 | stm32f301k6 = [ "stm32-metapac/stm32f301k6" ] | ||
| 229 | stm32f301k8 = [ "stm32-metapac/stm32f301k8" ] | ||
| 230 | stm32f301r6 = [ "stm32-metapac/stm32f301r6" ] | ||
| 231 | stm32f301r8 = [ "stm32-metapac/stm32f301r8" ] | ||
| 232 | stm32f302c6 = [ "stm32-metapac/stm32f302c6" ] | ||
| 233 | stm32f302c8 = [ "stm32-metapac/stm32f302c8" ] | ||
| 234 | stm32f302cb = [ "stm32-metapac/stm32f302cb" ] | ||
| 235 | stm32f302cc = [ "stm32-metapac/stm32f302cc" ] | ||
| 236 | stm32f302k6 = [ "stm32-metapac/stm32f302k6" ] | ||
| 237 | stm32f302k8 = [ "stm32-metapac/stm32f302k8" ] | ||
| 238 | stm32f302r6 = [ "stm32-metapac/stm32f302r6" ] | ||
| 239 | stm32f302r8 = [ "stm32-metapac/stm32f302r8" ] | ||
| 240 | stm32f302rb = [ "stm32-metapac/stm32f302rb" ] | ||
| 241 | stm32f302rc = [ "stm32-metapac/stm32f302rc" ] | ||
| 242 | stm32f302rd = [ "stm32-metapac/stm32f302rd" ] | ||
| 243 | stm32f302re = [ "stm32-metapac/stm32f302re" ] | ||
| 244 | stm32f302vb = [ "stm32-metapac/stm32f302vb" ] | ||
| 245 | stm32f302vc = [ "stm32-metapac/stm32f302vc" ] | ||
| 246 | stm32f302vd = [ "stm32-metapac/stm32f302vd" ] | ||
| 247 | stm32f302ve = [ "stm32-metapac/stm32f302ve" ] | ||
| 248 | stm32f302zd = [ "stm32-metapac/stm32f302zd" ] | ||
| 249 | stm32f302ze = [ "stm32-metapac/stm32f302ze" ] | ||
| 250 | stm32f303c6 = [ "stm32-metapac/stm32f303c6" ] | ||
| 251 | stm32f303c8 = [ "stm32-metapac/stm32f303c8" ] | ||
| 252 | stm32f303cb = [ "stm32-metapac/stm32f303cb" ] | ||
| 253 | stm32f303cc = [ "stm32-metapac/stm32f303cc" ] | ||
| 254 | stm32f303k6 = [ "stm32-metapac/stm32f303k6" ] | ||
| 255 | stm32f303k8 = [ "stm32-metapac/stm32f303k8" ] | ||
| 256 | stm32f303r6 = [ "stm32-metapac/stm32f303r6" ] | ||
| 257 | stm32f303r8 = [ "stm32-metapac/stm32f303r8" ] | ||
| 258 | stm32f303rb = [ "stm32-metapac/stm32f303rb" ] | ||
| 259 | stm32f303rc = [ "stm32-metapac/stm32f303rc" ] | ||
| 260 | stm32f303rd = [ "stm32-metapac/stm32f303rd" ] | ||
| 261 | stm32f303re = [ "stm32-metapac/stm32f303re" ] | ||
| 262 | stm32f303vb = [ "stm32-metapac/stm32f303vb" ] | ||
| 263 | stm32f303vc = [ "stm32-metapac/stm32f303vc" ] | ||
| 264 | stm32f303vd = [ "stm32-metapac/stm32f303vd" ] | ||
| 265 | stm32f303ve = [ "stm32-metapac/stm32f303ve" ] | ||
| 266 | stm32f303zd = [ "stm32-metapac/stm32f303zd" ] | ||
| 267 | stm32f303ze = [ "stm32-metapac/stm32f303ze" ] | ||
| 268 | stm32f318c8 = [ "stm32-metapac/stm32f318c8" ] | ||
| 269 | stm32f318k8 = [ "stm32-metapac/stm32f318k8" ] | ||
| 270 | stm32f328c8 = [ "stm32-metapac/stm32f328c8" ] | ||
| 271 | stm32f334c4 = [ "stm32-metapac/stm32f334c4" ] | ||
| 272 | stm32f334c6 = [ "stm32-metapac/stm32f334c6" ] | ||
| 273 | stm32f334c8 = [ "stm32-metapac/stm32f334c8" ] | ||
| 274 | stm32f334k4 = [ "stm32-metapac/stm32f334k4" ] | ||
| 275 | stm32f334k6 = [ "stm32-metapac/stm32f334k6" ] | ||
| 276 | stm32f334k8 = [ "stm32-metapac/stm32f334k8" ] | ||
| 277 | stm32f334r6 = [ "stm32-metapac/stm32f334r6" ] | ||
| 278 | stm32f334r8 = [ "stm32-metapac/stm32f334r8" ] | ||
| 279 | stm32f358cc = [ "stm32-metapac/stm32f358cc" ] | ||
| 280 | stm32f358rc = [ "stm32-metapac/stm32f358rc" ] | ||
| 281 | stm32f358vc = [ "stm32-metapac/stm32f358vc" ] | ||
| 282 | stm32f373c8 = [ "stm32-metapac/stm32f373c8" ] | ||
| 283 | stm32f373cb = [ "stm32-metapac/stm32f373cb" ] | ||
| 284 | stm32f373cc = [ "stm32-metapac/stm32f373cc" ] | ||
| 285 | stm32f373r8 = [ "stm32-metapac/stm32f373r8" ] | ||
| 286 | stm32f373rb = [ "stm32-metapac/stm32f373rb" ] | ||
| 287 | stm32f373rc = [ "stm32-metapac/stm32f373rc" ] | ||
| 288 | stm32f373v8 = [ "stm32-metapac/stm32f373v8" ] | ||
| 289 | stm32f373vb = [ "stm32-metapac/stm32f373vb" ] | ||
| 290 | stm32f373vc = [ "stm32-metapac/stm32f373vc" ] | ||
| 291 | stm32f378cc = [ "stm32-metapac/stm32f378cc" ] | ||
| 292 | stm32f378rc = [ "stm32-metapac/stm32f378rc" ] | ||
| 293 | stm32f378vc = [ "stm32-metapac/stm32f378vc" ] | ||
| 294 | stm32f398ve = [ "stm32-metapac/stm32f398ve" ] | ||
| 226 | stm32f401cb = [ "stm32-metapac/stm32f401cb" ] | 295 | stm32f401cb = [ "stm32-metapac/stm32f401cb" ] |
| 227 | stm32f401cc = [ "stm32-metapac/stm32f401cc" ] | 296 | stm32f401cc = [ "stm32-metapac/stm32f401cc" ] |
| 228 | stm32f401cd = [ "stm32-metapac/stm32f401cd" ] | 297 | stm32f401cd = [ "stm32-metapac/stm32f401cd" ] |
diff --git a/embassy-stm32/src/pwr/f3.rs b/embassy-stm32/src/pwr/f3.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/embassy-stm32/src/pwr/f3.rs | |||
| @@ -0,0 +1 @@ | |||
diff --git a/embassy-stm32/src/pwr/mod.rs b/embassy-stm32/src/pwr/mod.rs index a71ce8f3c..18f462bd2 100644 --- a/embassy-stm32/src/pwr/mod.rs +++ b/embassy-stm32/src/pwr/mod.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #[cfg_attr(any(pwr_h7, pwr_h7smps), path = "h7.rs")] | 1 | #[cfg_attr(any(pwr_h7, pwr_h7smps), path = "h7.rs")] |
| 2 | #[cfg_attr(pwr_f3, path = "f3.rs")] | ||
| 2 | #[cfg_attr(pwr_f4, path = "f4.rs")] | 3 | #[cfg_attr(pwr_f4, path = "f4.rs")] |
| 3 | #[cfg_attr(pwr_f7, path = "f7.rs")] | 4 | #[cfg_attr(pwr_f7, path = "f7.rs")] |
| 4 | #[cfg_attr(pwr_wl5, path = "wl5.rs")] | 5 | #[cfg_attr(pwr_wl5, path = "wl5.rs")] |
diff --git a/embassy-stm32/src/rcc/f3/mod.rs b/embassy-stm32/src/rcc/f3/mod.rs new file mode 100644 index 000000000..ab1bd7607 --- /dev/null +++ b/embassy-stm32/src/rcc/f3/mod.rs | |||
| @@ -0,0 +1,374 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | use embassy::util::Unborrow; | ||
| 3 | |||
| 4 | use crate::pac::{ | ||
| 5 | flash::vals::Latency, | ||
| 6 | rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}, | ||
| 7 | FLASH, RCC, | ||
| 8 | }; | ||
| 9 | use crate::peripherals; | ||
| 10 | use crate::rcc::{set_freqs, Clocks}; | ||
| 11 | use crate::time::Hertz; | ||
| 12 | |||
| 13 | const HSI: u32 = 8_000_000; | ||
| 14 | |||
| 15 | /// RCC peripheral | ||
| 16 | pub struct Rcc<'d> { | ||
| 17 | config: Config, | ||
| 18 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 19 | } | ||
| 20 | |||
| 21 | /// Clocks configutation | ||
| 22 | #[non_exhaustive] | ||
| 23 | #[derive(Default)] | ||
| 24 | pub struct Config { | ||
| 25 | /// Frequency of HSE oscillator | ||
| 26 | /// 4MHz to 32MHz | ||
| 27 | pub hse: Option<Hertz>, | ||
| 28 | /// Bypass HSE for an external clock | ||
| 29 | pub bypass_hse: bool, | ||
| 30 | /// Frequency of the System Clock | ||
| 31 | pub sysclk: Option<Hertz>, | ||
| 32 | /// Frequency of AHB bus | ||
| 33 | pub hclk: Option<Hertz>, | ||
| 34 | /// Frequency of APB1 bus | ||
| 35 | /// - Max frequency 36MHz | ||
| 36 | pub pclk1: Option<Hertz>, | ||
| 37 | /// Frequency of APB2 bus | ||
| 38 | /// - Max frequency with HSE is 72MHz | ||
| 39 | /// - Max frequency without HSE is 64MHz | ||
| 40 | pub pclk2: Option<Hertz>, | ||
| 41 | /// USB clock setup | ||
| 42 | /// It is valid only when, | ||
| 43 | /// - HSE is enabled, | ||
| 44 | /// - The System clock frequency is either 48MHz or 72MHz | ||
| 45 | /// - APB1 clock has a minimum frequency of 10MHz | ||
| 46 | pub pll48: bool, | ||
| 47 | } | ||
| 48 | |||
| 49 | // Information required to setup the PLL clock | ||
| 50 | struct PllConfig { | ||
| 51 | pll_src: Pllsrc, | ||
| 52 | pll_mul: Pllmul, | ||
| 53 | pll_div: Option<Prediv>, | ||
| 54 | } | ||
| 55 | |||
| 56 | /// Initialize and Set the clock frequencies | ||
| 57 | pub unsafe fn init(config: Config) { | ||
| 58 | let r = <peripherals::RCC as embassy::util::Steal>::steal(); | ||
| 59 | let clocks = Rcc::new(r, config).freeze(); | ||
| 60 | set_freqs(clocks); | ||
| 61 | } | ||
| 62 | |||
| 63 | impl<'d> Rcc<'d> { | ||
| 64 | pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { | ||
| 65 | Self { | ||
| 66 | config, | ||
| 67 | phantom: PhantomData, | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | fn freeze(self) -> Clocks { | ||
| 72 | // Calculate the real System clock, and PLL configuration if applicable | ||
| 73 | let (Hertz(sysclk), pll_config) = self.get_sysclk(); | ||
| 74 | assert!(sysclk <= 72_000_000); | ||
| 75 | |||
| 76 | // Calculate real AHB clock | ||
| 77 | let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk); | ||
| 78 | let (hpre_bits, hpre_div) = match sysclk / hclk { | ||
| 79 | 0 => unreachable!(), | ||
| 80 | 1 => (Hpre::DIV1, 1), | ||
| 81 | 2 => (Hpre::DIV2, 2), | ||
| 82 | 3..=5 => (Hpre::DIV4, 4), | ||
| 83 | 6..=11 => (Hpre::DIV8, 8), | ||
| 84 | 12..=39 => (Hpre::DIV16, 16), | ||
| 85 | 40..=95 => (Hpre::DIV64, 64), | ||
| 86 | 96..=191 => (Hpre::DIV128, 128), | ||
| 87 | 192..=383 => (Hpre::DIV256, 256), | ||
| 88 | _ => (Hpre::DIV512, 512), | ||
| 89 | }; | ||
| 90 | let hclk = sysclk / hpre_div; | ||
| 91 | assert!(hclk <= 72_000_000); | ||
| 92 | |||
| 93 | // Calculate real APB1 clock | ||
| 94 | let pclk1 = self.config.pclk1.map(|p| p.0).unwrap_or(hclk); | ||
| 95 | let (ppre1_bits, ppre1) = match hclk / pclk1 { | ||
| 96 | 0 => unreachable!(), | ||
| 97 | 1 => (Ppre::DIV1, 1), | ||
| 98 | 2 => (Ppre::DIV2, 2), | ||
| 99 | 3..=5 => (Ppre::DIV4, 4), | ||
| 100 | 6..=11 => (Ppre::DIV8, 8), | ||
| 101 | _ => (Ppre::DIV16, 16), | ||
| 102 | }; | ||
| 103 | let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; | ||
| 104 | let pclk1 = hclk / ppre1; | ||
| 105 | assert!(pclk1 <= 36_000_000); | ||
| 106 | |||
| 107 | // Calculate real APB2 clock | ||
| 108 | let pclk2 = self.config.pclk2.map(|p| p.0).unwrap_or(hclk); | ||
| 109 | let (ppre2_bits, ppre2) = match hclk / pclk2 { | ||
| 110 | 0 => unreachable!(), | ||
| 111 | 1 => (Ppre::DIV1, 1), | ||
| 112 | 2 => (Ppre::DIV2, 2), | ||
| 113 | 3..=5 => (Ppre::DIV4, 4), | ||
| 114 | 6..=11 => (Ppre::DIV8, 8), | ||
| 115 | _ => (Ppre::DIV16, 16), | ||
| 116 | }; | ||
| 117 | let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; | ||
| 118 | let pclk2 = hclk / ppre2; | ||
| 119 | assert!(pclk2 <= 72_000_000); | ||
| 120 | |||
| 121 | // Set latency based on HCLK frquency | ||
| 122 | // NOTE(safety) Atomic write | ||
| 123 | unsafe { | ||
| 124 | FLASH.acr().write(|w| { | ||
| 125 | w.set_latency(if hclk <= 24_000_000 { | ||
| 126 | Latency::WS0 | ||
| 127 | } else if hclk <= 48_000_000 { | ||
| 128 | Latency::WS1 | ||
| 129 | } else { | ||
| 130 | Latency::WS2 | ||
| 131 | }); | ||
| 132 | }) | ||
| 133 | } | ||
| 134 | |||
| 135 | // Enable HSE | ||
| 136 | if self.config.hse.is_some() { | ||
| 137 | // NOTE(unsafe) We own the peripheral block | ||
| 138 | unsafe { | ||
| 139 | RCC.cr().write(|w| { | ||
| 140 | w.set_hsebyp(if self.config.bypass_hse { | ||
| 141 | Hsebyp::BYPASSED | ||
| 142 | } else { | ||
| 143 | Hsebyp::NOTBYPASSED | ||
| 144 | }); | ||
| 145 | // We turn on clock security to switch to HSI when HSE fails | ||
| 146 | w.set_csson(true); | ||
| 147 | w.set_hseon(true); | ||
| 148 | }); | ||
| 149 | while !RCC.cr().read().hserdy() {} | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | // Enable PLL | ||
| 154 | if let Some(ref pll_config) = pll_config { | ||
| 155 | // NOTE(unsafe) We own the peripheral block | ||
| 156 | unsafe { | ||
| 157 | RCC.cfgr().write(|w| { | ||
| 158 | w.set_pllmul(pll_config.pll_mul); | ||
| 159 | w.set_pllsrc(pll_config.pll_src); | ||
| 160 | }); | ||
| 161 | if let Some(pll_div) = pll_config.pll_div { | ||
| 162 | RCC.cfgr2().write(|w| w.set_prediv(pll_div)); | ||
| 163 | } | ||
| 164 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 165 | while !RCC.cr().read().pllrdy() {} | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | if self.config.pll48 { | ||
| 170 | let usb_pre = self.get_usb_pre(sysclk, pclk1, &pll_config); | ||
| 171 | // NOTE(unsafe) We own the peripheral block | ||
| 172 | unsafe { | ||
| 173 | RCC.cfgr().write(|w| { | ||
| 174 | w.set_usbpre(usb_pre); | ||
| 175 | }); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | // Set prescalers | ||
| 180 | unsafe { | ||
| 181 | // NOTE(unsafe) We own the peripheral block | ||
| 182 | RCC.cfgr().write(|w| { | ||
| 183 | w.set_ppre2(ppre2_bits); | ||
| 184 | w.set_ppre1(ppre1_bits); | ||
| 185 | w.set_hpre(hpre_bits); | ||
| 186 | }); | ||
| 187 | |||
| 188 | // Wait for the new prescalers to kick in | ||
| 189 | // "The clocks are divided with the new prescaler factor from | ||
| 190 | // 1 to 16 AHB cycles after write" | ||
| 191 | cortex_m::asm::delay(16); | ||
| 192 | |||
| 193 | // NOTE(unsafe) We own the peripheral block | ||
| 194 | RCC.cfgr().write(|w| { | ||
| 195 | w.set_sw(match (pll_config, self.config.hse) { | ||
| 196 | (Some(_), _) => Sw::PLL, | ||
| 197 | (None, Some(_)) => Sw::HSE, | ||
| 198 | (None, None) => Sw::HSI, | ||
| 199 | }) | ||
| 200 | }); | ||
| 201 | } | ||
| 202 | |||
| 203 | Clocks { | ||
| 204 | sys: Hertz(sysclk), | ||
| 205 | apb1: Hertz(pclk1), | ||
| 206 | apb2: Hertz(pclk2), | ||
| 207 | apb1_tim: Hertz(pclk1 * timer_mul1), | ||
| 208 | apb2_tim: Hertz(pclk2 * timer_mul2), | ||
| 209 | ahb: Hertz(hclk), | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | #[inline] | ||
| 214 | fn get_sysclk(&self) -> (Hertz, Option<PllConfig>) { | ||
| 215 | match (self.config.sysclk, self.config.hse) { | ||
| 216 | (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None), | ||
| 217 | (Some(sysclk), None) if sysclk.0 == HSI => (Hertz(HSI), None), | ||
| 218 | // If the user selected System clock is different from HSI or HSE | ||
| 219 | // we will have to setup PLL clock source | ||
| 220 | (Some(sysclk), _) => { | ||
| 221 | let (sysclk, pll_config) = self.calc_pll(sysclk); | ||
| 222 | (sysclk, Some(pll_config)) | ||
| 223 | } | ||
| 224 | (None, Some(hse)) => (hse, None), | ||
| 225 | (None, None) => (Hertz(HSI), None), | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | #[inline] | ||
| 230 | fn calc_pll(&self, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { | ||
| 231 | // Calculates the Multiplier and the Divisor to arrive at | ||
| 232 | // the required System clock from PLL source frequency | ||
| 233 | let get_mul_div = |sysclk, pllsrcclk| { | ||
| 234 | let common_div = gcd(sysclk, pllsrcclk); | ||
| 235 | let mut multiplier = sysclk / common_div; | ||
| 236 | let mut divisor = pllsrcclk / common_div; | ||
| 237 | // Minimum PLL multiplier is two | ||
| 238 | if multiplier == 1 { | ||
| 239 | multiplier *= 2; | ||
| 240 | divisor *= 2; | ||
| 241 | } | ||
| 242 | assert!(multiplier <= 16); | ||
| 243 | assert!(divisor <= 16); | ||
| 244 | (multiplier, divisor) | ||
| 245 | }; | ||
| 246 | // Based on the source of Pll, we calculate the actual system clock | ||
| 247 | // frequency, PLL's source identifier, multiplier and divisor | ||
| 248 | let (act_sysclk, pll_src, pll_mul, pll_div) = match self.config.hse { | ||
| 249 | Some(Hertz(hse)) => { | ||
| 250 | let (multiplier, divisor) = get_mul_div(sysclk, hse); | ||
| 251 | ( | ||
| 252 | Hertz((hse / divisor) * multiplier), | ||
| 253 | Pllsrc::HSE_DIV_PREDIV, | ||
| 254 | into_pll_mul(multiplier), | ||
| 255 | Some(into_pre_div(divisor)), | ||
| 256 | ) | ||
| 257 | } | ||
| 258 | None => { | ||
| 259 | cfg_if::cfg_if! { | ||
| 260 | // For some chips PREDIV is always two, and cannot be changed | ||
| 261 | if #[cfg(any( | ||
| 262 | feature="stm32f302xd", feature="stm32f302xe", feature="stm32f303xd", | ||
| 263 | feature="stm32f303xe", feature="stm32f398xe" | ||
| 264 | ))] { | ||
| 265 | let (multiplier, divisor) = get_mul_div(sysclk, HSI); | ||
| 266 | ( | ||
| 267 | Hertz((hse / divisor) * multiplier), | ||
| 268 | Pllsrc::HSI_DIV_PREDIV, | ||
| 269 | into_pll_mul(multiplier), | ||
| 270 | Some(into_pre_div(divisor)), | ||
| 271 | ) | ||
| 272 | } else { | ||
| 273 | let pllsrcclk = HSI / 2; | ||
| 274 | let multiplier = sysclk / pllsrcclk; | ||
| 275 | assert!(multiplier <= 16); | ||
| 276 | ( | ||
| 277 | Hertz(pllsrcclk * multiplier), | ||
| 278 | Pllsrc::HSI_DIV2, | ||
| 279 | into_pll_mul(multiplier), | ||
| 280 | None, | ||
| 281 | ) | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | }; | ||
| 286 | ( | ||
| 287 | act_sysclk, | ||
| 288 | PllConfig { | ||
| 289 | pll_src, | ||
| 290 | pll_mul, | ||
| 291 | pll_div, | ||
| 292 | }, | ||
| 293 | ) | ||
| 294 | } | ||
| 295 | |||
| 296 | #[inline] | ||
| 297 | fn get_usb_pre(&self, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre { | ||
| 298 | cfg_if::cfg_if! { | ||
| 299 | // Some chips do not have USB | ||
| 300 | if #[cfg(any(stm32f301, stm32f318, stm32f334))] { | ||
| 301 | panic!("USB clock not supported by the chip"); | ||
| 302 | } else { | ||
| 303 | let usb_ok = self.config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000); | ||
| 304 | match (usb_ok, sysclk) { | ||
| 305 | (true, 72_000_000) => Usbpre::DIV1_5, | ||
| 306 | (true, 48_000_000) => Usbpre::DIV1, | ||
| 307 | _ => panic!( | ||
| 308 | "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz" | ||
| 309 | ), | ||
| 310 | } | ||
| 311 | } | ||
| 312 | } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | // This function assumes cases when multiplier is one and it | ||
| 317 | // being greater than 16 is made impossible | ||
| 318 | #[inline] | ||
| 319 | fn into_pll_mul(multiplier: u32) -> Pllmul { | ||
| 320 | match multiplier { | ||
| 321 | 2 => Pllmul::MUL2, | ||
| 322 | 3 => Pllmul::MUL3, | ||
| 323 | 4 => Pllmul::MUL4, | ||
| 324 | 5 => Pllmul::MUL5, | ||
| 325 | 6 => Pllmul::MUL6, | ||
| 326 | 7 => Pllmul::MUL7, | ||
| 327 | 8 => Pllmul::MUL8, | ||
| 328 | 9 => Pllmul::MUL9, | ||
| 329 | 10 => Pllmul::MUL10, | ||
| 330 | 11 => Pllmul::MUL11, | ||
| 331 | 12 => Pllmul::MUL12, | ||
| 332 | 13 => Pllmul::MUL13, | ||
| 333 | 14 => Pllmul::MUL14, | ||
| 334 | 15 => Pllmul::MUL15, | ||
| 335 | 16 => Pllmul::MUL16, | ||
| 336 | _ => unreachable!(), | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | // This function assumes the incoming divisor cannot be greater | ||
| 341 | // than 16 | ||
| 342 | #[inline] | ||
| 343 | fn into_pre_div(divisor: u32) -> Prediv { | ||
| 344 | match divisor { | ||
| 345 | 1 => Prediv::DIV1, | ||
| 346 | 2 => Prediv::DIV2, | ||
| 347 | 3 => Prediv::DIV3, | ||
| 348 | 4 => Prediv::DIV4, | ||
| 349 | 5 => Prediv::DIV5, | ||
| 350 | 6 => Prediv::DIV6, | ||
| 351 | 7 => Prediv::DIV7, | ||
| 352 | 8 => Prediv::DIV8, | ||
| 353 | 9 => Prediv::DIV9, | ||
| 354 | 10 => Prediv::DIV10, | ||
| 355 | 11 => Prediv::DIV11, | ||
| 356 | 12 => Prediv::DIV12, | ||
| 357 | 13 => Prediv::DIV13, | ||
| 358 | 14 => Prediv::DIV14, | ||
| 359 | 15 => Prediv::DIV15, | ||
| 360 | 16 => Prediv::DIV16, | ||
| 361 | _ => unreachable!(), | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | // Determine GCD using Euclidean algorithm | ||
| 366 | #[inline] | ||
| 367 | fn gcd(mut a: u32, mut b: u32) -> u32 { | ||
| 368 | while b != 0 { | ||
| 369 | let r = a % b; | ||
| 370 | a = b; | ||
| 371 | b = r; | ||
| 372 | } | ||
| 373 | a | ||
| 374 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 9883543df..619316df8 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -26,7 +26,7 @@ pub struct Clocks { | |||
| 26 | #[cfg(any(rcc_wl5, rcc_u5))] | 26 | #[cfg(any(rcc_wl5, rcc_u5))] |
| 27 | pub apb3: Hertz, | 27 | pub apb3: Hertz, |
| 28 | 28 | ||
| 29 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f0x0, rcc_g0))] | 29 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f3, rcc_f0x0, rcc_g0))] |
| 30 | pub ahb: Hertz, | 30 | pub ahb: Hertz, |
| 31 | 31 | ||
| 32 | #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_g4, rcc_u5, rcc_wb, rcc_wl5))] | 32 | #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_g4, rcc_u5, rcc_wb, rcc_wl5))] |
| @@ -81,6 +81,9 @@ cfg_if::cfg_if! { | |||
| 81 | } else if #[cfg(rcc_f1)] { | 81 | } else if #[cfg(rcc_f1)] { |
| 82 | mod f1; | 82 | mod f1; |
| 83 | pub use f1::*; | 83 | pub use f1::*; |
| 84 | } else if #[cfg(rcc_f3)] { | ||
| 85 | mod f3; | ||
| 86 | pub use f3::*; | ||
| 84 | } else if #[cfg(rcc_f4)] { | 87 | } else if #[cfg(rcc_f4)] { |
| 85 | mod f4; | 88 | mod f4; |
| 86 | pub use f4::*; | 89 | pub use f4::*; |
diff --git a/examples/stm32f3/.cargo/config.toml b/examples/stm32f3/.cargo/config.toml new file mode 100644 index 000000000..eb8a8b335 --- /dev/null +++ b/examples/stm32f3/.cargo/config.toml | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace STM32F429ZITx with your chip as listed in `probe-run --list-chips` | ||
| 3 | runner = "probe-run --chip STM32F303VCTx" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "thumbv7em-none-eabihf" | ||
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml new file mode 100644 index 000000000..cd9cd3a8f --- /dev/null +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | [package] | ||
| 2 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 3 | edition = "2018" | ||
| 4 | name = "embassy-stm32f3-examples" | ||
| 5 | version = "0.1.0" | ||
| 6 | resolver = "2" | ||
| 7 | |||
| 8 | [dependencies] | ||
| 9 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } | ||
| 10 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | ||
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f303vc", "unstable-pac", "memory-x", "time-driver-tim2"] } | ||
| 12 | |||
| 13 | defmt = "0.3" | ||
| 14 | defmt-rtt = "0.3" | ||
| 15 | |||
| 16 | cortex-m = "0.7.3" | ||
| 17 | cortex-m-rt = "0.7.0" | ||
| 18 | embedded-hal = "0.2.6" | ||
| 19 | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||
| 20 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||
| 21 | heapless = { version = "0.7.5", default-features = false } | ||
| 22 | nb = "1.0.0" | ||
diff --git a/examples/stm32f3/build.rs b/examples/stm32f3/build.rs new file mode 100644 index 000000000..8cd32d7ed --- /dev/null +++ b/examples/stm32f3/build.rs | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | fn main() { | ||
| 2 | println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| 3 | println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| 4 | println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||
| 5 | } | ||
diff --git a/examples/stm32f3/src/bin/blinky.rs b/examples/stm32f3/src/bin/blinky.rs new file mode 100644 index 000000000..321643557 --- /dev/null +++ b/examples/stm32f3/src/bin/blinky.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | |||
| 8 | use embassy::executor::Spawner; | ||
| 9 | use embassy::time::{Duration, Timer}; | ||
| 10 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 11 | use embassy_stm32::Peripherals; | ||
| 12 | use embedded_hal::digital::v2::OutputPin; | ||
| 13 | use example_common::*; | ||
| 14 | |||
| 15 | #[embassy::main] | ||
| 16 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 17 | info!("Hello World!"); | ||
| 18 | |||
| 19 | let mut led = Output::new(p.PE12, Level::High, Speed::Low); | ||
| 20 | |||
| 21 | loop { | ||
| 22 | info!("high"); | ||
| 23 | unwrap!(led.set_high()); | ||
| 24 | Timer::after(Duration::from_millis(1000)).await; | ||
| 25 | |||
| 26 | info!("low"); | ||
| 27 | unwrap!(led.set_low()); | ||
| 28 | Timer::after(Duration::from_millis(1000)).await; | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/examples/stm32f3/src/bin/button.rs b/examples/stm32f3/src/bin/button.rs new file mode 100644 index 000000000..c5fab138b --- /dev/null +++ b/examples/stm32f3/src/bin/button.rs | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use cortex_m_rt::entry; | ||
| 8 | use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | ||
| 9 | use embedded_hal::digital::v2::{InputPin, OutputPin}; | ||
| 10 | use example_common::*; | ||
| 11 | |||
| 12 | #[entry] | ||
| 13 | fn main() -> ! { | ||
| 14 | info!("Hello World!"); | ||
| 15 | |||
| 16 | let p = embassy_stm32::init(Default::default()); | ||
| 17 | |||
| 18 | let button = Input::new(p.PA0, Pull::Down); | ||
| 19 | let mut led1 = Output::new(p.PE9, Level::High, Speed::Low); | ||
| 20 | let mut led2 = Output::new(p.PE15, Level::High, Speed::Low); | ||
| 21 | |||
| 22 | loop { | ||
| 23 | if unwrap!(button.is_high()) { | ||
| 24 | info!("high"); | ||
| 25 | unwrap!(led1.set_high()); | ||
| 26 | unwrap!(led2.set_low()); | ||
| 27 | } else { | ||
| 28 | info!("low"); | ||
| 29 | unwrap!(led1.set_low()); | ||
| 30 | unwrap!(led2.set_high()); | ||
| 31 | } | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs new file mode 100644 index 000000000..d45e4365b --- /dev/null +++ b/examples/stm32f3/src/bin/button_exti.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use embassy::executor::Spawner; | ||
| 8 | use embassy_stm32::exti::ExtiInput; | ||
| 9 | use embassy_stm32::gpio::{Input, Pull}; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge}; | ||
| 12 | use example_common::*; | ||
| 13 | |||
| 14 | #[embassy::main] | ||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 16 | info!("Hello World!"); | ||
| 17 | |||
| 18 | let button = Input::new(p.PA0, Pull::Down); | ||
| 19 | let mut button = ExtiInput::new(button, p.EXTI0); | ||
| 20 | |||
| 21 | info!("Press the USER button..."); | ||
| 22 | |||
| 23 | loop { | ||
| 24 | button.wait_for_rising_edge().await; | ||
| 25 | info!("Pressed!"); | ||
| 26 | button.wait_for_falling_edge().await; | ||
| 27 | info!("Released!"); | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/examples/stm32f3/src/bin/hello.rs b/examples/stm32f3/src/bin/hello.rs new file mode 100644 index 000000000..9a67419fb --- /dev/null +++ b/examples/stm32f3/src/bin/hello.rs | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::info; | ||
| 6 | use embassy::executor::Spawner; | ||
| 7 | use embassy::time::{Duration, Timer}; | ||
| 8 | use embassy_stm32::time::Hertz; | ||
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | |||
| 12 | #[path = "../example_common.rs"] | ||
| 13 | mod example_common; | ||
| 14 | |||
| 15 | fn config() -> Config { | ||
| 16 | let mut config = Config::default(); | ||
| 17 | config.rcc.hse = Some(Hertz(8_000_000)); | ||
| 18 | config.rcc.sysclk = Some(Hertz(16_000_000)); | ||
| 19 | config | ||
| 20 | } | ||
| 21 | |||
| 22 | #[embassy::main(config = "config()")] | ||
| 23 | async fn main(_spawner: Spawner, _p: Peripherals) -> ! { | ||
| 24 | loop { | ||
| 25 | info!("Hello World!"); | ||
| 26 | Timer::after(Duration::from_secs(1)).await; | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/examples/stm32f3/src/bin/spi_dma.rs b/examples/stm32f3/src/bin/spi_dma.rs new file mode 100644 index 000000000..a87a36f73 --- /dev/null +++ b/examples/stm32f3/src/bin/spi_dma.rs | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use core::fmt::Write; | ||
| 8 | use core::str::from_utf8; | ||
| 9 | use embassy::executor::Spawner; | ||
| 10 | use embassy_stm32::spi::{Config, Spi}; | ||
| 11 | use embassy_stm32::time::Hertz; | ||
| 12 | use embassy_stm32::Peripherals; | ||
| 13 | use embassy_traits::spi::FullDuplex; | ||
| 14 | use example_common::*; | ||
| 15 | use heapless::String; | ||
| 16 | |||
| 17 | #[embassy::main] | ||
| 18 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 19 | info!("Hello World!"); | ||
| 20 | |||
| 21 | let mut spi = Spi::new( | ||
| 22 | p.SPI1, | ||
| 23 | p.PB3, | ||
| 24 | p.PB5, | ||
| 25 | p.PB4, | ||
| 26 | p.DMA1_CH3, | ||
| 27 | p.DMA1_CH2, | ||
| 28 | Hertz(1_000_000), | ||
| 29 | Config::default(), | ||
| 30 | ); | ||
| 31 | |||
| 32 | for n in 0u32.. { | ||
| 33 | let mut write: String<128> = String::new(); | ||
| 34 | let mut read = [0; 128]; | ||
| 35 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); | ||
| 36 | spi.read_write(&mut read[0..write.len()], write.as_bytes()) | ||
| 37 | .await | ||
| 38 | .ok(); | ||
| 39 | info!("read via spi+dma: {}", from_utf8(&read).unwrap()); | ||
| 40 | } | ||
| 41 | } | ||
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs new file mode 100644 index 000000000..99530b5c0 --- /dev/null +++ b/examples/stm32f3/src/bin/usart_dma.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use core::fmt::Write; | ||
| 8 | use embassy::executor::Spawner; | ||
| 9 | use embassy_stm32::dma::NoDma; | ||
| 10 | use embassy_stm32::usart::{Config, Uart}; | ||
| 11 | use embassy_stm32::Peripherals; | ||
| 12 | use embassy_traits::uart::Write as _; | ||
| 13 | use example_common::*; | ||
| 14 | use heapless::String; | ||
| 15 | |||
| 16 | #[embassy::main] | ||
| 17 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 18 | info!("Hello World!"); | ||
| 19 | |||
| 20 | let config = Config::default(); | ||
| 21 | let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, p.DMA1_CH4, NoDma, config); | ||
| 22 | |||
| 23 | for n in 0u32.. { | ||
| 24 | let mut s: String<128> = String::new(); | ||
| 25 | core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); | ||
| 26 | |||
| 27 | unwrap!(usart.write(s.as_bytes()).await); | ||
| 28 | info!("wrote DMA"); | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/examples/stm32f3/src/example_common.rs b/examples/stm32f3/src/example_common.rs new file mode 100644 index 000000000..e14517033 --- /dev/null +++ b/examples/stm32f3/src/example_common.rs | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | use defmt_rtt as _; // global logger | ||
| 4 | use panic_probe as _; | ||
| 5 | |||
| 6 | pub use defmt::*; | ||
| 7 | |||
| 8 | use core::sync::atomic::{AtomicUsize, Ordering}; | ||
| 9 | |||
| 10 | defmt::timestamp! { | ||
| 11 | "{=u64}", | ||
| 12 | { | ||
| 13 | static COUNT: AtomicUsize = AtomicUsize::new(0); | ||
| 14 | // NOTE(no-CAS) `timestamps` runs with interrupts disabled | ||
| 15 | let n = COUNT.load(Ordering::Relaxed); | ||
| 16 | COUNT.store(n + 1, Ordering::Relaxed); | ||
| 17 | n as u64 | ||
| 18 | } | ||
| 19 | } | ||
diff --git a/stm32-data b/stm32-data | |||
| Subproject 5506d27471c7e3297450127c3279f3dab96c94f | Subproject f275c3f5ef23339e068f38e1790584277a24623 | ||
diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index 50c334852..1ab4865a4 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs | |||
| @@ -5,6 +5,7 @@ use std::{iter::FilterMap, path::Path, slice::Iter}; | |||
| 5 | const SUPPORTED_FAMILIES: &[&str] = &[ | 5 | const SUPPORTED_FAMILIES: &[&str] = &[ |
| 6 | "stm32f0", | 6 | "stm32f0", |
| 7 | "stm32f1", | 7 | "stm32f1", |
| 8 | "stm32f3", | ||
| 8 | "stm32f4", | 9 | "stm32f4", |
| 9 | "stm32f7", | 10 | "stm32f7", |
| 10 | "stm32g0", | 11 | "stm32g0", |
