diff options
| author | Matous Hybl <[email protected]> | 2021-10-19 15:36:41 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-10-26 17:33:28 +0200 |
| commit | 015cad84dddf684673399c181b2782353fa405a8 (patch) | |
| tree | 4e4f171f6e68a3fec352f34c2878a34a7bcbb36d | |
| parent | 7cb34760c4bd4d98f38437c36769c54c56047a10 (diff) | |
Initial support for STM32F767ZI.
| -rw-r--r-- | embassy-stm32/Cargo.toml | 88 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/can/bxcan.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/v1.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/pwr/f7.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/pwr/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f7/max.rs | 19 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f7/mod.rs | 347 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 9 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc/v1.rs | 1 | ||||
| -rw-r--r-- | examples/stm32f7/.cargo/config.toml | 18 | ||||
| -rw-r--r-- | examples/stm32f7/Cargo.toml | 35 | ||||
| -rw-r--r-- | examples/stm32f7/build.rs | 39 | ||||
| -rw-r--r-- | examples/stm32f7/memory.x | 12 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/blinky.rs | 29 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/button.rs | 34 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/button_exti.rs | 29 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/hello.rs | 27 | ||||
| -rw-r--r-- | examples/stm32f7/src/example_common.rs | 17 | ||||
| m--------- | stm32-data | 0 | ||||
| -rw-r--r-- | stm32-gen-features/src/lib.rs | 3 |
24 files changed, 711 insertions, 6 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b2f863377..ecad19751 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -378,6 +378,94 @@ stm32f479vg = [ "stm32-metapac/stm32f479vg" ] | |||
| 378 | stm32f479vi = [ "stm32-metapac/stm32f479vi" ] | 378 | stm32f479vi = [ "stm32-metapac/stm32f479vi" ] |
| 379 | stm32f479zg = [ "stm32-metapac/stm32f479zg" ] | 379 | stm32f479zg = [ "stm32-metapac/stm32f479zg" ] |
| 380 | stm32f479zi = [ "stm32-metapac/stm32f479zi" ] | 380 | stm32f479zi = [ "stm32-metapac/stm32f479zi" ] |
| 381 | stm32f722ic = [ "stm32-metapac/stm32f722ic" ] | ||
| 382 | stm32f722ie = [ "stm32-metapac/stm32f722ie" ] | ||
| 383 | stm32f722rc = [ "stm32-metapac/stm32f722rc" ] | ||
| 384 | stm32f722re = [ "stm32-metapac/stm32f722re" ] | ||
| 385 | stm32f722vc = [ "stm32-metapac/stm32f722vc" ] | ||
| 386 | stm32f722ve = [ "stm32-metapac/stm32f722ve" ] | ||
| 387 | stm32f722zc = [ "stm32-metapac/stm32f722zc" ] | ||
| 388 | stm32f722ze = [ "stm32-metapac/stm32f722ze" ] | ||
| 389 | stm32f723ic = [ "stm32-metapac/stm32f723ic" ] | ||
| 390 | stm32f723ie = [ "stm32-metapac/stm32f723ie" ] | ||
| 391 | stm32f723vc = [ "stm32-metapac/stm32f723vc" ] | ||
| 392 | stm32f723ve = [ "stm32-metapac/stm32f723ve" ] | ||
| 393 | stm32f723zc = [ "stm32-metapac/stm32f723zc" ] | ||
| 394 | stm32f723ze = [ "stm32-metapac/stm32f723ze" ] | ||
| 395 | stm32f730i8 = [ "stm32-metapac/stm32f730i8" ] | ||
| 396 | stm32f730r8 = [ "stm32-metapac/stm32f730r8" ] | ||
| 397 | stm32f730v8 = [ "stm32-metapac/stm32f730v8" ] | ||
| 398 | stm32f730z8 = [ "stm32-metapac/stm32f730z8" ] | ||
| 399 | stm32f732ie = [ "stm32-metapac/stm32f732ie" ] | ||
| 400 | stm32f732re = [ "stm32-metapac/stm32f732re" ] | ||
| 401 | stm32f732ve = [ "stm32-metapac/stm32f732ve" ] | ||
| 402 | stm32f732ze = [ "stm32-metapac/stm32f732ze" ] | ||
| 403 | stm32f733ie = [ "stm32-metapac/stm32f733ie" ] | ||
| 404 | stm32f733ve = [ "stm32-metapac/stm32f733ve" ] | ||
| 405 | stm32f733ze = [ "stm32-metapac/stm32f733ze" ] | ||
| 406 | stm32f745ie = [ "stm32-metapac/stm32f745ie" ] | ||
| 407 | stm32f745ig = [ "stm32-metapac/stm32f745ig" ] | ||
| 408 | stm32f745ve = [ "stm32-metapac/stm32f745ve" ] | ||
| 409 | stm32f745vg = [ "stm32-metapac/stm32f745vg" ] | ||
| 410 | stm32f745ze = [ "stm32-metapac/stm32f745ze" ] | ||
| 411 | stm32f745zg = [ "stm32-metapac/stm32f745zg" ] | ||
| 412 | stm32f746be = [ "stm32-metapac/stm32f746be" ] | ||
| 413 | stm32f746bg = [ "stm32-metapac/stm32f746bg" ] | ||
| 414 | stm32f746ie = [ "stm32-metapac/stm32f746ie" ] | ||
| 415 | stm32f746ig = [ "stm32-metapac/stm32f746ig" ] | ||
| 416 | stm32f746ne = [ "stm32-metapac/stm32f746ne" ] | ||
| 417 | stm32f746ng = [ "stm32-metapac/stm32f746ng" ] | ||
| 418 | stm32f746ve = [ "stm32-metapac/stm32f746ve" ] | ||
| 419 | stm32f746vg = [ "stm32-metapac/stm32f746vg" ] | ||
| 420 | stm32f746ze = [ "stm32-metapac/stm32f746ze" ] | ||
| 421 | stm32f746zg = [ "stm32-metapac/stm32f746zg" ] | ||
| 422 | stm32f750n8 = [ "stm32-metapac/stm32f750n8" ] | ||
| 423 | stm32f750v8 = [ "stm32-metapac/stm32f750v8" ] | ||
| 424 | stm32f750z8 = [ "stm32-metapac/stm32f750z8" ] | ||
| 425 | stm32f756bg = [ "stm32-metapac/stm32f756bg" ] | ||
| 426 | stm32f756ig = [ "stm32-metapac/stm32f756ig" ] | ||
| 427 | stm32f756ng = [ "stm32-metapac/stm32f756ng" ] | ||
| 428 | stm32f756vg = [ "stm32-metapac/stm32f756vg" ] | ||
| 429 | stm32f756zg = [ "stm32-metapac/stm32f756zg" ] | ||
| 430 | stm32f765bg = [ "stm32-metapac/stm32f765bg" ] | ||
| 431 | stm32f765bi = [ "stm32-metapac/stm32f765bi" ] | ||
| 432 | stm32f765ig = [ "stm32-metapac/stm32f765ig" ] | ||
| 433 | stm32f765ii = [ "stm32-metapac/stm32f765ii" ] | ||
| 434 | stm32f765ng = [ "stm32-metapac/stm32f765ng" ] | ||
| 435 | stm32f765ni = [ "stm32-metapac/stm32f765ni" ] | ||
| 436 | stm32f765vg = [ "stm32-metapac/stm32f765vg" ] | ||
| 437 | stm32f765vi = [ "stm32-metapac/stm32f765vi" ] | ||
| 438 | stm32f765zg = [ "stm32-metapac/stm32f765zg" ] | ||
| 439 | stm32f765zi = [ "stm32-metapac/stm32f765zi" ] | ||
| 440 | stm32f767bg = [ "stm32-metapac/stm32f767bg" ] | ||
| 441 | stm32f767bi = [ "stm32-metapac/stm32f767bi" ] | ||
| 442 | stm32f767ig = [ "stm32-metapac/stm32f767ig" ] | ||
| 443 | stm32f767ii = [ "stm32-metapac/stm32f767ii" ] | ||
| 444 | stm32f767ng = [ "stm32-metapac/stm32f767ng" ] | ||
| 445 | stm32f767ni = [ "stm32-metapac/stm32f767ni" ] | ||
| 446 | stm32f767vg = [ "stm32-metapac/stm32f767vg" ] | ||
| 447 | stm32f767vi = [ "stm32-metapac/stm32f767vi" ] | ||
| 448 | stm32f767zg = [ "stm32-metapac/stm32f767zg" ] | ||
| 449 | stm32f767zi = [ "stm32-metapac/stm32f767zi" ] | ||
| 450 | stm32f768ai = [ "stm32-metapac/stm32f768ai" ] | ||
| 451 | stm32f769ag = [ "stm32-metapac/stm32f769ag" ] | ||
| 452 | stm32f769ai = [ "stm32-metapac/stm32f769ai" ] | ||
| 453 | stm32f769bg = [ "stm32-metapac/stm32f769bg" ] | ||
| 454 | stm32f769bi = [ "stm32-metapac/stm32f769bi" ] | ||
| 455 | stm32f769ig = [ "stm32-metapac/stm32f769ig" ] | ||
| 456 | stm32f769ii = [ "stm32-metapac/stm32f769ii" ] | ||
| 457 | stm32f769ng = [ "stm32-metapac/stm32f769ng" ] | ||
| 458 | stm32f769ni = [ "stm32-metapac/stm32f769ni" ] | ||
| 459 | stm32f777bi = [ "stm32-metapac/stm32f777bi" ] | ||
| 460 | stm32f777ii = [ "stm32-metapac/stm32f777ii" ] | ||
| 461 | stm32f777ni = [ "stm32-metapac/stm32f777ni" ] | ||
| 462 | stm32f777vi = [ "stm32-metapac/stm32f777vi" ] | ||
| 463 | stm32f777zi = [ "stm32-metapac/stm32f777zi" ] | ||
| 464 | stm32f778ai = [ "stm32-metapac/stm32f778ai" ] | ||
| 465 | stm32f779ai = [ "stm32-metapac/stm32f779ai" ] | ||
| 466 | stm32f779bi = [ "stm32-metapac/stm32f779bi" ] | ||
| 467 | stm32f779ii = [ "stm32-metapac/stm32f779ii" ] | ||
| 468 | stm32f779ni = [ "stm32-metapac/stm32f779ni" ] | ||
| 381 | stm32g030c6 = [ "stm32-metapac/stm32g030c6" ] | 469 | stm32g030c6 = [ "stm32-metapac/stm32g030c6" ] |
| 382 | stm32g030c8 = [ "stm32-metapac/stm32g030c8" ] | 470 | stm32g030c8 = [ "stm32-metapac/stm32g030c8" ] |
| 383 | stm32g030f6 = [ "stm32-metapac/stm32g030f6" ] | 471 | stm32g030f6 = [ "stm32-metapac/stm32g030f6" ] |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index f292d0208..9c3a30fbc 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | #[cfg_attr(adc_v3, path = "v3.rs")] | 3 | #[cfg_attr(adc_v3, path = "v3.rs")] |
| 4 | #[cfg_attr(adc_v2, path = "v2.rs")] | ||
| 4 | #[cfg_attr(adc_g0, path = "v3.rs")] | 5 | #[cfg_attr(adc_g0, path = "v3.rs")] |
| 5 | mod _version; | 6 | mod _version; |
| 6 | 7 | ||
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -0,0 +1 @@ | |||
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index b73b88391..191fc42a1 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -119,7 +119,7 @@ crate::pac::peripherals!( | |||
| 119 | unsafe impl bxcan::MasterInstance for peripherals::CAN1 {} | 119 | unsafe impl bxcan::MasterInstance for peripherals::CAN1 {} |
| 120 | }; | 120 | }; |
| 121 | (can, CAN3) => { | 121 | (can, CAN3) => { |
| 122 | unsafe impl bxcan::FilterOwner for peripherals::$inst { | 122 | unsafe impl bxcan::FilterOwner for peripherals::CAN3 { |
| 123 | const NUM_FILTER_BANKS: u8 = 14; | 123 | const NUM_FILTER_BANKS: u8 = 14; |
| 124 | } | 124 | } |
| 125 | }; | 125 | }; |
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 0a15563ef..a54c40833 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | #[cfg_attr(dac_v1, path = "v1.rs")] | ||
| 3 | #[cfg_attr(dac_v2, path = "v2.rs")] | 4 | #[cfg_attr(dac_v2, path = "v2.rs")] |
| 4 | mod _version; | 5 | mod _version; |
| 5 | use crate::gpio::NoPin; | 6 | use crate::gpio::NoPin; |
diff --git a/embassy-stm32/src/dac/v1.rs b/embassy-stm32/src/dac/v1.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/embassy-stm32/src/dac/v1.rs | |||
| @@ -0,0 +1 @@ | |||
diff --git a/embassy-stm32/src/pwr/f7.rs b/embassy-stm32/src/pwr/f7.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/embassy-stm32/src/pwr/f7.rs | |||
| @@ -0,0 +1 @@ | |||
diff --git a/embassy-stm32/src/pwr/mod.rs b/embassy-stm32/src/pwr/mod.rs index 37f7e572e..2577eab34 100644 --- a/embassy-stm32/src/pwr/mod.rs +++ b/embassy-stm32/src/pwr/mod.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 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_f4, path = "f4.rs")] | 2 | #[cfg_attr(pwr_f4, path = "f4.rs")] |
| 3 | #[cfg_attr(pwr_f7, path = "f7.rs")] | ||
| 3 | #[cfg_attr(pwr_wl5, path = "wl5.rs")] | 4 | #[cfg_attr(pwr_wl5, path = "wl5.rs")] |
| 4 | #[cfg_attr(pwr_g0, path = "g0.rs")] | 5 | #[cfg_attr(pwr_g0, path = "g0.rs")] |
| 5 | #[cfg_attr(pwr_l1, path = "l1.rs")] | 6 | #[cfg_attr(pwr_l1, path = "l1.rs")] |
diff --git a/embassy-stm32/src/rcc/f7/max.rs b/embassy-stm32/src/rcc/f7/max.rs new file mode 100644 index 000000000..db00fdf3e --- /dev/null +++ b/embassy-stm32/src/rcc/f7/max.rs | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | pub(crate) const HSE_OSC_MIN: u32 = 4_000_000; | ||
| 2 | pub(crate) const HSE_OSC_MAX: u32 = 26_000_000; | ||
| 3 | pub(crate) const HSE_BYPASS_MIN: u32 = 1_000_000; | ||
| 4 | pub(crate) const HSE_BYPASS_MAX: u32 = 50_000_000; | ||
| 5 | |||
| 6 | pub(crate) const HCLK_MAX: u32 = 216_000_000; | ||
| 7 | pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 180_000_000; | ||
| 8 | |||
| 9 | pub(crate) const SYSCLK_MIN: u32 = 12_500_000; | ||
| 10 | pub(crate) const SYSCLK_MAX: u32 = 216_000_000; | ||
| 11 | |||
| 12 | pub(crate) const PCLK1_MIN: u32 = SYSCLK_MIN; | ||
| 13 | pub(crate) const PCLK1_MAX: u32 = SYSCLK_MAX / 4; | ||
| 14 | |||
| 15 | pub(crate) const PCLK2_MIN: u32 = SYSCLK_MIN; | ||
| 16 | pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2; | ||
| 17 | |||
| 18 | pub(crate) const PLL_48_CLK: u32 = 48_000_000; | ||
| 19 | pub(crate) const PLL_48_TOLERANCE: u32 = 120_000; | ||
diff --git a/embassy-stm32/src/rcc/f7/mod.rs b/embassy-stm32/src/rcc/f7/mod.rs new file mode 100644 index 000000000..c13e20167 --- /dev/null +++ b/embassy-stm32/src/rcc/f7/mod.rs | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | mod max; | ||
| 2 | |||
| 3 | use crate::pac::{FLASH, PWR, RCC}; | ||
| 4 | use crate::peripherals; | ||
| 5 | use crate::rcc::{get_freqs, set_freqs, Clocks}; | ||
| 6 | use crate::time::Hertz; | ||
| 7 | use core::marker::PhantomData; | ||
| 8 | use embassy::util::Unborrow; | ||
| 9 | |||
| 10 | const HSI: u32 = 16_000_000; | ||
| 11 | |||
| 12 | #[non_exhaustive] | ||
| 13 | #[derive(Default)] | ||
| 14 | pub struct Config { | ||
| 15 | pub hse: Option<Hertz>, | ||
| 16 | pub bypass_hse: bool, | ||
| 17 | pub hclk: Option<Hertz>, | ||
| 18 | pub sys_ck: Option<Hertz>, | ||
| 19 | pub pclk1: Option<Hertz>, | ||
| 20 | pub pclk2: Option<Hertz>, | ||
| 21 | |||
| 22 | pub pll48: bool, | ||
| 23 | } | ||
| 24 | |||
| 25 | /// RCC peripheral | ||
| 26 | pub struct Rcc<'d> { | ||
| 27 | config: Config, | ||
| 28 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 29 | } | ||
| 30 | |||
| 31 | impl<'d> Rcc<'d> { | ||
| 32 | pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { | ||
| 33 | if let Some(hse) = config.hse { | ||
| 34 | if config.bypass_hse { | ||
| 35 | assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0)); | ||
| 36 | } else { | ||
| 37 | assert!((max::HSE_OSC_MIN..=max::HSE_OSC_MAX).contains(&hse.0)); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | Self { | ||
| 41 | config, | ||
| 42 | phantom: PhantomData, | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | fn freeze(mut self) -> Clocks { | ||
| 47 | use super::sealed::RccPeripheral; | ||
| 48 | use crate::pac::pwr::vals::Vos; | ||
| 49 | use crate::pac::rcc::vals::{Hpre, Hsebyp, Ppre, Sw}; | ||
| 50 | |||
| 51 | let base_clock = self.config.hse.map(|hse| hse.0).unwrap_or(HSI); | ||
| 52 | let sysclk = self.config.sys_ck.map(|sys| sys.0).unwrap_or(base_clock); | ||
| 53 | let sysclk_on_pll = sysclk != base_clock; | ||
| 54 | |||
| 55 | assert!((max::SYSCLK_MIN..=max::SYSCLK_MAX).contains(&sysclk)); | ||
| 56 | |||
| 57 | let plls = self.setup_pll( | ||
| 58 | base_clock, | ||
| 59 | self.config.hse.is_some(), | ||
| 60 | if sysclk_on_pll { Some(sysclk) } else { None }, | ||
| 61 | self.config.pll48, | ||
| 62 | ); | ||
| 63 | |||
| 64 | if self.config.pll48 { | ||
| 65 | assert!( | ||
| 66 | // USB specification allows +-0.25% | ||
| 67 | plls.pll48clk | ||
| 68 | .map(|freq| (max::PLL_48_CLK as i32 - freq as i32).abs() | ||
| 69 | <= max::PLL_48_TOLERANCE as i32) | ||
| 70 | .unwrap_or(false) | ||
| 71 | ); | ||
| 72 | } | ||
| 73 | |||
| 74 | let sysclk = if sysclk_on_pll { | ||
| 75 | unwrap!(plls.pllsysclk) | ||
| 76 | } else { | ||
| 77 | sysclk | ||
| 78 | }; | ||
| 79 | |||
| 80 | // AHB prescaler | ||
| 81 | let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk); | ||
| 82 | let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk { | ||
| 83 | 0 => unreachable!(), | ||
| 84 | 1 => (Hpre::DIV1, 1), | ||
| 85 | 2 => (Hpre::DIV2, 2), | ||
| 86 | 3..=5 => (Hpre::DIV4, 4), | ||
| 87 | 6..=11 => (Hpre::DIV8, 8), | ||
| 88 | 12..=39 => (Hpre::DIV16, 16), | ||
| 89 | 40..=95 => (Hpre::DIV64, 64), | ||
| 90 | 96..=191 => (Hpre::DIV128, 128), | ||
| 91 | 192..=383 => (Hpre::DIV256, 256), | ||
| 92 | _ => (Hpre::DIV512, 512), | ||
| 93 | }; | ||
| 94 | |||
| 95 | // Calculate real AHB clock | ||
| 96 | let hclk = sysclk / hpre_div; | ||
| 97 | |||
| 98 | assert!(hclk < max::HCLK_MAX); | ||
| 99 | |||
| 100 | let pclk1 = self | ||
| 101 | .config | ||
| 102 | .pclk1 | ||
| 103 | .map(|p| p.0) | ||
| 104 | .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk)); | ||
| 105 | |||
| 106 | let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 { | ||
| 107 | 0 => unreachable!(), | ||
| 108 | 1 => (0b000, 1), | ||
| 109 | 2 => (0b100, 2), | ||
| 110 | 3..=5 => (0b101, 4), | ||
| 111 | 6..=11 => (0b110, 8), | ||
| 112 | _ => (0b111, 16), | ||
| 113 | }; | ||
| 114 | let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; | ||
| 115 | |||
| 116 | // Calculate real APB1 clock | ||
| 117 | let pclk1 = hclk / ppre1; | ||
| 118 | assert!((max::PCLK1_MIN..=max::PCLK1_MAX).contains(&pclk1)); | ||
| 119 | |||
| 120 | let pclk2 = self | ||
| 121 | .config | ||
| 122 | .pclk2 | ||
| 123 | .map(|p| p.0) | ||
| 124 | .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk)); | ||
| 125 | let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 { | ||
| 126 | 0 => unreachable!(), | ||
| 127 | 1 => (0b000, 1), | ||
| 128 | 2 => (0b100, 2), | ||
| 129 | 3..=5 => (0b101, 4), | ||
| 130 | 6..=11 => (0b110, 8), | ||
| 131 | _ => (0b111, 16), | ||
| 132 | }; | ||
| 133 | let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; | ||
| 134 | |||
| 135 | // Calculate real APB2 clock | ||
| 136 | let pclk2 = hclk / ppre2; | ||
| 137 | assert!((max::PCLK2_MIN..=max::PCLK2_MAX).contains(&pclk2)); | ||
| 138 | |||
| 139 | Self::flash_setup(sysclk); | ||
| 140 | |||
| 141 | if self.config.hse.is_some() { | ||
| 142 | // NOTE(unsafe) We own the peripheral block | ||
| 143 | unsafe { | ||
| 144 | RCC.cr().modify(|w| { | ||
| 145 | w.set_hsebyp(Hsebyp(self.config.bypass_hse as u8)); | ||
| 146 | w.set_hseon(true); | ||
| 147 | }); | ||
| 148 | while !RCC.cr().read().hserdy() {} | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | if plls.use_pll { | ||
| 153 | unsafe { | ||
| 154 | RCC.cr().modify(|w| w.set_pllon(false)); | ||
| 155 | |||
| 156 | // enable PWR and setup VOSScale | ||
| 157 | |||
| 158 | RCC.apb1enr().modify(|w| w.set_pwren(true)); | ||
| 159 | |||
| 160 | let vos_scale = if sysclk <= 144_000_000 { | ||
| 161 | 3 | ||
| 162 | } else if sysclk <= 168_000_000 { | ||
| 163 | 2 | ||
| 164 | } else { | ||
| 165 | 1 | ||
| 166 | }; | ||
| 167 | PWR.cr1().modify(|w| { | ||
| 168 | w.set_vos(match vos_scale { | ||
| 169 | 3 => Vos::SCALE3, | ||
| 170 | 2 => Vos::SCALE2, | ||
| 171 | 1 => Vos::SCALE1, | ||
| 172 | _ => panic!("Invalid VOS Scale."), | ||
| 173 | }) | ||
| 174 | }); | ||
| 175 | |||
| 176 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 177 | |||
| 178 | while !RCC.cr().read().pllrdy() {} | ||
| 179 | |||
| 180 | if hclk > max::HCLK_OVERDRIVE_FREQUENCY { | ||
| 181 | peripherals::PWR::enable(); | ||
| 182 | |||
| 183 | PWR.cr1().modify(|w| w.set_oden(true)); | ||
| 184 | while !PWR.csr1().read().odrdy() {} | ||
| 185 | |||
| 186 | PWR.cr1().modify(|w| w.set_odswen(true)); | ||
| 187 | while !PWR.csr1().read().odswrdy() {} | ||
| 188 | } | ||
| 189 | |||
| 190 | while !RCC.cr().read().pllrdy() {} | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | unsafe { | ||
| 195 | RCC.cfgr().modify(|w| { | ||
| 196 | w.set_ppre2(Ppre(ppre2_bits)); | ||
| 197 | w.set_ppre1(Ppre(ppre1_bits)); | ||
| 198 | w.set_hpre(hpre_bits); | ||
| 199 | }); | ||
| 200 | |||
| 201 | // Wait for the new prescalers to kick in | ||
| 202 | // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write" | ||
| 203 | cortex_m::asm::delay(16); | ||
| 204 | |||
| 205 | RCC.cfgr().modify(|w| { | ||
| 206 | w.set_sw(if sysclk_on_pll { | ||
| 207 | Sw::PLL | ||
| 208 | } else if self.config.hse.is_some() { | ||
| 209 | Sw::HSE | ||
| 210 | } else { | ||
| 211 | Sw::HSI | ||
| 212 | }) | ||
| 213 | }); | ||
| 214 | } | ||
| 215 | |||
| 216 | Clocks { | ||
| 217 | sys: Hertz(sysclk), | ||
| 218 | apb1: Hertz(pclk1), | ||
| 219 | apb2: Hertz(pclk2), | ||
| 220 | |||
| 221 | apb1_tim: Hertz(pclk1 * timer_mul1), | ||
| 222 | apb2_tim: Hertz(pclk2 * timer_mul2), | ||
| 223 | |||
| 224 | ahb1: Hertz(hclk), | ||
| 225 | ahb2: Hertz(hclk), | ||
| 226 | ahb3: Hertz(hclk), | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | // Safety: RCC init must have been called | ||
| 231 | pub fn clocks(&self) -> &'static Clocks { | ||
| 232 | unsafe { get_freqs() } | ||
| 233 | } | ||
| 234 | |||
| 235 | fn setup_pll( | ||
| 236 | &mut self, | ||
| 237 | pllsrcclk: u32, | ||
| 238 | use_hse: bool, | ||
| 239 | pllsysclk: Option<u32>, | ||
| 240 | pll48clk: bool, | ||
| 241 | ) -> PllResults { | ||
| 242 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; | ||
| 243 | |||
| 244 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); | ||
| 245 | if pllsysclk.is_none() && !pll48clk { | ||
| 246 | // NOTE(unsafe) We have a mutable borrow to the owner of the RegBlock | ||
| 247 | unsafe { | ||
| 248 | RCC.pllcfgr() | ||
| 249 | .modify(|w| w.set_pllsrc(Pllsrc(use_hse as u8))); | ||
| 250 | } | ||
| 251 | |||
| 252 | return PllResults { | ||
| 253 | use_pll: false, | ||
| 254 | pllsysclk: None, | ||
| 255 | pll48clk: None, | ||
| 256 | }; | ||
| 257 | } | ||
| 258 | // Input divisor from PLL source clock, must result to frequency in | ||
| 259 | // the range from 1 to 2 MHz | ||
| 260 | let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000; | ||
| 261 | let pllm_max = pllsrcclk / 1_000_000; | ||
| 262 | |||
| 263 | // Sysclk output divisor must be one of 2, 4, 6 or 8 | ||
| 264 | let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1); | ||
| 265 | |||
| 266 | let target_freq = if pll48clk { | ||
| 267 | 48_000_000 | ||
| 268 | } else { | ||
| 269 | sysclk * sysclk_div | ||
| 270 | }; | ||
| 271 | |||
| 272 | // Find the lowest pllm value that minimize the difference between | ||
| 273 | // target frequency and the real vco_out frequency. | ||
| 274 | let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| { | ||
| 275 | let vco_in = pllsrcclk / pllm; | ||
| 276 | let plln = target_freq / vco_in; | ||
| 277 | target_freq - vco_in * plln | ||
| 278 | })); | ||
| 279 | |||
| 280 | let vco_in = pllsrcclk / pllm; | ||
| 281 | assert!((1_000_000..=2_000_000).contains(&vco_in)); | ||
| 282 | |||
| 283 | // Main scaler, must result in >= 100MHz (>= 192MHz for F401) | ||
| 284 | // and <= 432MHz, min 50, max 432 | ||
| 285 | let plln = if pll48clk { | ||
| 286 | // try the different valid pllq according to the valid | ||
| 287 | // main scaller values, and take the best | ||
| 288 | let pllq = unwrap!((4..=9).min_by_key(|pllq| { | ||
| 289 | let plln = 48_000_000 * pllq / vco_in; | ||
| 290 | let pll48_diff = 48_000_000 - vco_in * plln / pllq; | ||
| 291 | let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs(); | ||
| 292 | (pll48_diff, sysclk_diff) | ||
| 293 | })); | ||
| 294 | 48_000_000 * pllq / vco_in | ||
| 295 | } else { | ||
| 296 | sysclk * sysclk_div / vco_in | ||
| 297 | }; | ||
| 298 | |||
| 299 | let pllp = (sysclk_div / 2) - 1; | ||
| 300 | |||
| 301 | let pllq = (vco_in * plln + 47_999_999) / 48_000_000; | ||
| 302 | let real_pll48clk = vco_in * plln / pllq; | ||
| 303 | |||
| 304 | unsafe { | ||
| 305 | RCC.pllcfgr().modify(|w| { | ||
| 306 | w.set_pllm(pllm as u8); | ||
| 307 | w.set_plln(plln as u16); | ||
| 308 | w.set_pllp(Pllp(pllp as u8)); | ||
| 309 | w.set_pllq(pllq as u8); | ||
| 310 | w.set_pllsrc(Pllsrc(use_hse as u8)); | ||
| 311 | }); | ||
| 312 | } | ||
| 313 | |||
| 314 | let real_pllsysclk = vco_in * plln / sysclk_div; | ||
| 315 | |||
| 316 | PllResults { | ||
| 317 | use_pll: true, | ||
| 318 | pllsysclk: Some(real_pllsysclk), | ||
| 319 | pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | fn flash_setup(sysclk: u32) { | ||
| 324 | use crate::pac::flash::vals::Latency; | ||
| 325 | |||
| 326 | // Be conservative with voltage ranges | ||
| 327 | const FLASH_LATENCY_STEP: u32 = 30_000_000; | ||
| 328 | |||
| 329 | critical_section::with(|_| unsafe { | ||
| 330 | FLASH | ||
| 331 | .acr() | ||
| 332 | .modify(|w| w.set_latency(Latency(((sysclk - 1) / FLASH_LATENCY_STEP) as u8))); | ||
| 333 | }); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | pub unsafe fn init(config: Config) { | ||
| 338 | let r = <peripherals::RCC as embassy::util::Steal>::steal(); | ||
| 339 | let clocks = Rcc::new(r, config).freeze(); | ||
| 340 | set_freqs(clocks); | ||
| 341 | } | ||
| 342 | |||
| 343 | struct PllResults { | ||
| 344 | use_pll: bool, | ||
| 345 | pllsysclk: Option<u32>, | ||
| 346 | pll48clk: Option<u32>, | ||
| 347 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index ef1d6a859..28def28ab 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -30,13 +30,13 @@ pub struct Clocks { | |||
| 30 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f0x0, rcc_g0))] | 30 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f0x0, rcc_g0))] |
| 31 | pub ahb: Hertz, | 31 | pub ahb: Hertz, |
| 32 | 32 | ||
| 33 | #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))] | 33 | #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_wb, rcc_wl5))] |
| 34 | pub ahb1: Hertz, | 34 | pub ahb1: Hertz, |
| 35 | 35 | ||
| 36 | #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))] | 36 | #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_wb, rcc_wl5))] |
| 37 | pub ahb2: Hertz, | 37 | pub ahb2: Hertz, |
| 38 | 38 | ||
| 39 | #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))] | 39 | #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_wb, rcc_wl5))] |
| 40 | pub ahb3: Hertz, | 40 | pub ahb3: Hertz, |
| 41 | 41 | ||
| 42 | #[cfg(any(rcc_h7))] | 42 | #[cfg(any(rcc_h7))] |
| @@ -85,6 +85,9 @@ cfg_if::cfg_if! { | |||
| 85 | } else if #[cfg(rcc_f4)] { | 85 | } else if #[cfg(rcc_f4)] { |
| 86 | mod f4; | 86 | mod f4; |
| 87 | pub use f4::*; | 87 | pub use f4::*; |
| 88 | } else if #[cfg(rcc_f7)] { | ||
| 89 | mod f7; | ||
| 90 | pub use f7::*; | ||
| 88 | } else if #[cfg(rcc_wb)] { | 91 | } else if #[cfg(rcc_wb)] { |
| 89 | mod wb; | 92 | mod wb; |
| 90 | pub use wb::*; | 93 | pub use wb::*; |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 9244c22a6..087cb4c40 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | //#[cfg_attr(sdmmc_v1, path = "v1.rs")] | 3 | #[cfg_attr(sdmmc_v1, path = "v1.rs")] |
| 4 | #[cfg_attr(sdmmc_v2, path = "v2.rs")] | 4 | #[cfg_attr(sdmmc_v2, path = "v2.rs")] |
| 5 | mod _version; | 5 | mod _version; |
| 6 | 6 | ||
diff --git a/embassy-stm32/src/sdmmc/v1.rs b/embassy-stm32/src/sdmmc/v1.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/embassy-stm32/src/sdmmc/v1.rs | |||
| @@ -0,0 +1 @@ | |||
diff --git a/examples/stm32f7/.cargo/config.toml b/examples/stm32f7/.cargo/config.toml new file mode 100644 index 000000000..632e81541 --- /dev/null +++ b/examples/stm32f7/.cargo/config.toml | |||
| @@ -0,0 +1,18 @@ | |||
| 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 STM32F767ZITx" | ||
| 4 | |||
| 5 | rustflags = [ | ||
| 6 | # LLD (shipped with the Rust toolchain) is used as the default linker | ||
| 7 | "-C", "link-arg=--nmagic", | ||
| 8 | "-C", "link-arg=-Tlink.x", | ||
| 9 | "-C", "link-arg=-Tdefmt.x", | ||
| 10 | |||
| 11 | # Code-size optimizations. | ||
| 12 | "-Z", "trap-unreachable=no", | ||
| 13 | "-C", "inline-threshold=5", | ||
| 14 | "-C", "no-vectorize-loops", | ||
| 15 | ] | ||
| 16 | |||
| 17 | [build] | ||
| 18 | target = "thumbv7em-none-eabihf" | ||
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml new file mode 100644 index 000000000..cda2d7778 --- /dev/null +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 3 | edition = "2018" | ||
| 4 | name = "embassy-stm32f7-examples" | ||
| 5 | version = "0.1.0" | ||
| 6 | resolver = "2" | ||
| 7 | |||
| 8 | [features] | ||
| 9 | default = [ | ||
| 10 | "defmt-default", | ||
| 11 | ] | ||
| 12 | defmt-default = [] | ||
| 13 | defmt-trace = [] | ||
| 14 | defmt-debug = [] | ||
| 15 | defmt-info = [] | ||
| 16 | defmt-warn = [] | ||
| 17 | defmt-error = [] | ||
| 18 | |||
| 19 | [dependencies] | ||
| 20 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] } | ||
| 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | ||
| 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32f767zi", "unstable-pac", "time-driver-tim2"] } | ||
| 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | ||
| 24 | |||
| 25 | defmt = "0.2.3" | ||
| 26 | defmt-rtt = "0.2.0" | ||
| 27 | |||
| 28 | cortex-m = "0.7.3" | ||
| 29 | cortex-m-rt = "0.7.0" | ||
| 30 | embedded-hal = "0.2.6" | ||
| 31 | panic-probe = { version = "0.2.0", features = ["print-defmt"] } | ||
| 32 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||
| 33 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } | ||
| 34 | heapless = { version = "0.7.5", default-features = false } | ||
| 35 | nb = "1.0.0" | ||
diff --git a/examples/stm32f7/build.rs b/examples/stm32f7/build.rs new file mode 100644 index 000000000..b81f6b6e1 --- /dev/null +++ b/examples/stm32f7/build.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | //! adapted from https://github.com/stm32-rs/stm32f7xx-hal/blob/master/build.rs | ||
| 2 | use std::env; | ||
| 3 | use std::fs::File; | ||
| 4 | use std::io::{self, prelude::*}; | ||
| 5 | use std::path::PathBuf; | ||
| 6 | |||
| 7 | #[derive(Debug)] | ||
| 8 | enum Error { | ||
| 9 | Env(env::VarError), | ||
| 10 | Io(io::Error), | ||
| 11 | } | ||
| 12 | |||
| 13 | impl From<env::VarError> for Error { | ||
| 14 | fn from(error: env::VarError) -> Self { | ||
| 15 | Self::Env(error) | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | impl From<io::Error> for Error { | ||
| 20 | fn from(error: io::Error) -> Self { | ||
| 21 | Self::Io(error) | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | fn main() -> Result<(), Error> { | ||
| 26 | println!("cargo:rerun-if-changed=build.rs"); | ||
| 27 | println!("cargo:rerun-if-changed=memory.x"); | ||
| 28 | |||
| 29 | let out_dir = env::var("OUT_DIR")?; | ||
| 30 | let out_dir = PathBuf::from(out_dir); | ||
| 31 | |||
| 32 | let memory_x = include_bytes!("memory.x").as_ref(); | ||
| 33 | File::create(out_dir.join("memory.x"))?.write_all(memory_x)?; | ||
| 34 | |||
| 35 | // Tell Cargo where to find the file. | ||
| 36 | println!("cargo:rustc-link-search={}", out_dir.display()); | ||
| 37 | |||
| 38 | Ok(()) | ||
| 39 | } | ||
diff --git a/examples/stm32f7/memory.x b/examples/stm32f7/memory.x new file mode 100644 index 000000000..899f7a4b8 --- /dev/null +++ b/examples/stm32f7/memory.x | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | /* For STM32F765,767,768,769,777,778,779 devices */ | ||
| 2 | MEMORY | ||
| 3 | { | ||
| 4 | /* NOTE K = KiBi = 1024 bytes */ | ||
| 5 | FLASH : ORIGIN = 0x08000000, LENGTH = 2M | ||
| 6 | RAM : ORIGIN = 0x20000000, LENGTH = 368K + 16K | ||
| 7 | } | ||
| 8 | |||
| 9 | /* This is where the call stack will be allocated. */ | ||
| 10 | /* The stack is of the full descending type. */ | ||
| 11 | /* NOTE Do NOT modify `_stack_start` unless you know what you are doing */ | ||
| 12 | _stack_start = ORIGIN(RAM) + LENGTH(RAM); | ||
diff --git a/examples/stm32f7/src/bin/blinky.rs b/examples/stm32f7/src/bin/blinky.rs new file mode 100644 index 000000000..c4857195f --- /dev/null +++ b/examples/stm32f7/src/bin/blinky.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::time::{Duration, Timer}; | ||
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | use embedded_hal::digital::v2::OutputPin; | ||
| 12 | use example_common::*; | ||
| 13 | |||
| 14 | #[embassy::main] | ||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 16 | info!("Hello World!"); | ||
| 17 | |||
| 18 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); | ||
| 19 | |||
| 20 | loop { | ||
| 21 | info!("high"); | ||
| 22 | unwrap!(led.set_high()); | ||
| 23 | Timer::after(Duration::from_millis(300)).await; | ||
| 24 | |||
| 25 | info!("low"); | ||
| 26 | unwrap!(led.set_low()); | ||
| 27 | Timer::after(Duration::from_millis(300)).await; | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/examples/stm32f7/src/bin/button.rs b/examples/stm32f7/src/bin/button.rs new file mode 100644 index 000000000..95dee7c74 --- /dev/null +++ b/examples/stm32f7/src/bin/button.rs | |||
| @@ -0,0 +1,34 @@ | |||
| 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.PC13, Pull::Down); | ||
| 19 | let mut led1 = Output::new(p.PB0, Level::High, Speed::Low); | ||
| 20 | let _led2 = Output::new(p.PB7, Level::High, Speed::Low); | ||
| 21 | let mut led3 = Output::new(p.PB14, Level::High, Speed::Low); | ||
| 22 | |||
| 23 | loop { | ||
| 24 | if unwrap!(button.is_high()) { | ||
| 25 | info!("high"); | ||
| 26 | unwrap!(led1.set_high()); | ||
| 27 | unwrap!(led3.set_low()); | ||
| 28 | } else { | ||
| 29 | info!("low"); | ||
| 30 | unwrap!(led1.set_low()); | ||
| 31 | unwrap!(led3.set_high()); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | } | ||
diff --git a/examples/stm32f7/src/bin/button_exti.rs b/examples/stm32f7/src/bin/button_exti.rs new file mode 100644 index 000000000..2c4318d64 --- /dev/null +++ b/examples/stm32f7/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.PC13, Pull::Down); | ||
| 19 | let mut button = ExtiInput::new(button, p.EXTI13); | ||
| 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/stm32f7/src/bin/hello.rs b/examples/stm32f7/src/bin/hello.rs new file mode 100644 index 000000000..56eb67bf3 --- /dev/null +++ b/examples/stm32f7/src/bin/hello.rs | |||
| @@ -0,0 +1,27 @@ | |||
| 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.sys_ck = Some(Hertz(84_000_000)); | ||
| 18 | config | ||
| 19 | } | ||
| 20 | |||
| 21 | #[embassy::main(config = "config()")] | ||
| 22 | async fn main(_spawner: Spawner, _p: Peripherals) -> ! { | ||
| 23 | loop { | ||
| 24 | info!("Hello World!"); | ||
| 25 | Timer::after(Duration::from_secs(1)).await; | ||
| 26 | } | ||
| 27 | } | ||
diff --git a/examples/stm32f7/src/example_common.rs b/examples/stm32f7/src/example_common.rs new file mode 100644 index 000000000..54d633837 --- /dev/null +++ b/examples/stm32f7/src/example_common.rs | |||
| @@ -0,0 +1,17 @@ | |||
| 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! {"{=u64}", { | ||
| 11 | static COUNT: AtomicUsize = AtomicUsize::new(0); | ||
| 12 | // NOTE(no-CAS) `timestamps` runs with interrupts disabled | ||
| 13 | let n = COUNT.load(Ordering::Relaxed); | ||
| 14 | COUNT.store(n + 1, Ordering::Relaxed); | ||
| 15 | n as u64 | ||
| 16 | } | ||
| 17 | } | ||
diff --git a/stm32-data b/stm32-data | |||
| Subproject bae2d34445f87e7b9a88b683c789c5d0c7560fb | Subproject 4972ce0a2a4cf2722f334809ada7be4cc6e4b61 | ||
diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index 426984cb0..381fd1c17 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs | |||
| @@ -2,10 +2,11 @@ | |||
| 2 | 2 | ||
| 3 | use std::{iter::FilterMap, path::Path, slice::Iter}; | 3 | use std::{iter::FilterMap, path::Path, slice::Iter}; |
| 4 | 4 | ||
| 5 | const SUPPORTED_FAMILIES: [&str; 10] = [ | 5 | const SUPPORTED_FAMILIES: [&str; 11] = [ |
| 6 | "stm32f0", | 6 | "stm32f0", |
| 7 | "stm32f1", | 7 | "stm32f1", |
| 8 | "stm32f4", | 8 | "stm32f4", |
| 9 | "stm32f7", | ||
| 9 | "stm32g0", | 10 | "stm32g0", |
| 10 | "stm32l0", | 11 | "stm32l0", |
| 11 | "stm32l1", | 12 | "stm32l1", |
