aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatous Hybl <[email protected]>2021-10-19 15:36:41 +0200
committerDario Nieuwenhuis <[email protected]>2021-10-26 17:33:28 +0200
commit015cad84dddf684673399c181b2782353fa405a8 (patch)
tree4e4f171f6e68a3fec352f34c2878a34a7bcbb36d
parent7cb34760c4bd4d98f38437c36769c54c56047a10 (diff)
Initial support for STM32F767ZI.
-rw-r--r--embassy-stm32/Cargo.toml88
-rw-r--r--embassy-stm32/src/adc/mod.rs1
-rw-r--r--embassy-stm32/src/adc/v2.rs1
-rw-r--r--embassy-stm32/src/can/bxcan.rs2
-rw-r--r--embassy-stm32/src/dac/mod.rs1
-rw-r--r--embassy-stm32/src/dac/v1.rs1
-rw-r--r--embassy-stm32/src/pwr/f7.rs1
-rw-r--r--embassy-stm32/src/pwr/mod.rs1
-rw-r--r--embassy-stm32/src/rcc/f7/max.rs19
-rw-r--r--embassy-stm32/src/rcc/f7/mod.rs347
-rw-r--r--embassy-stm32/src/rcc/mod.rs9
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs2
-rw-r--r--embassy-stm32/src/sdmmc/v1.rs1
-rw-r--r--examples/stm32f7/.cargo/config.toml18
-rw-r--r--examples/stm32f7/Cargo.toml35
-rw-r--r--examples/stm32f7/build.rs39
-rw-r--r--examples/stm32f7/memory.x12
-rw-r--r--examples/stm32f7/src/bin/blinky.rs29
-rw-r--r--examples/stm32f7/src/bin/button.rs34
-rw-r--r--examples/stm32f7/src/bin/button_exti.rs29
-rw-r--r--examples/stm32f7/src/bin/hello.rs27
-rw-r--r--examples/stm32f7/src/example_common.rs17
m---------stm32-data0
-rw-r--r--stm32-gen-features/src/lib.rs3
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" ]
378stm32f479vi = [ "stm32-metapac/stm32f479vi" ] 378stm32f479vi = [ "stm32-metapac/stm32f479vi" ]
379stm32f479zg = [ "stm32-metapac/stm32f479zg" ] 379stm32f479zg = [ "stm32-metapac/stm32f479zg" ]
380stm32f479zi = [ "stm32-metapac/stm32f479zi" ] 380stm32f479zi = [ "stm32-metapac/stm32f479zi" ]
381stm32f722ic = [ "stm32-metapac/stm32f722ic" ]
382stm32f722ie = [ "stm32-metapac/stm32f722ie" ]
383stm32f722rc = [ "stm32-metapac/stm32f722rc" ]
384stm32f722re = [ "stm32-metapac/stm32f722re" ]
385stm32f722vc = [ "stm32-metapac/stm32f722vc" ]
386stm32f722ve = [ "stm32-metapac/stm32f722ve" ]
387stm32f722zc = [ "stm32-metapac/stm32f722zc" ]
388stm32f722ze = [ "stm32-metapac/stm32f722ze" ]
389stm32f723ic = [ "stm32-metapac/stm32f723ic" ]
390stm32f723ie = [ "stm32-metapac/stm32f723ie" ]
391stm32f723vc = [ "stm32-metapac/stm32f723vc" ]
392stm32f723ve = [ "stm32-metapac/stm32f723ve" ]
393stm32f723zc = [ "stm32-metapac/stm32f723zc" ]
394stm32f723ze = [ "stm32-metapac/stm32f723ze" ]
395stm32f730i8 = [ "stm32-metapac/stm32f730i8" ]
396stm32f730r8 = [ "stm32-metapac/stm32f730r8" ]
397stm32f730v8 = [ "stm32-metapac/stm32f730v8" ]
398stm32f730z8 = [ "stm32-metapac/stm32f730z8" ]
399stm32f732ie = [ "stm32-metapac/stm32f732ie" ]
400stm32f732re = [ "stm32-metapac/stm32f732re" ]
401stm32f732ve = [ "stm32-metapac/stm32f732ve" ]
402stm32f732ze = [ "stm32-metapac/stm32f732ze" ]
403stm32f733ie = [ "stm32-metapac/stm32f733ie" ]
404stm32f733ve = [ "stm32-metapac/stm32f733ve" ]
405stm32f733ze = [ "stm32-metapac/stm32f733ze" ]
406stm32f745ie = [ "stm32-metapac/stm32f745ie" ]
407stm32f745ig = [ "stm32-metapac/stm32f745ig" ]
408stm32f745ve = [ "stm32-metapac/stm32f745ve" ]
409stm32f745vg = [ "stm32-metapac/stm32f745vg" ]
410stm32f745ze = [ "stm32-metapac/stm32f745ze" ]
411stm32f745zg = [ "stm32-metapac/stm32f745zg" ]
412stm32f746be = [ "stm32-metapac/stm32f746be" ]
413stm32f746bg = [ "stm32-metapac/stm32f746bg" ]
414stm32f746ie = [ "stm32-metapac/stm32f746ie" ]
415stm32f746ig = [ "stm32-metapac/stm32f746ig" ]
416stm32f746ne = [ "stm32-metapac/stm32f746ne" ]
417stm32f746ng = [ "stm32-metapac/stm32f746ng" ]
418stm32f746ve = [ "stm32-metapac/stm32f746ve" ]
419stm32f746vg = [ "stm32-metapac/stm32f746vg" ]
420stm32f746ze = [ "stm32-metapac/stm32f746ze" ]
421stm32f746zg = [ "stm32-metapac/stm32f746zg" ]
422stm32f750n8 = [ "stm32-metapac/stm32f750n8" ]
423stm32f750v8 = [ "stm32-metapac/stm32f750v8" ]
424stm32f750z8 = [ "stm32-metapac/stm32f750z8" ]
425stm32f756bg = [ "stm32-metapac/stm32f756bg" ]
426stm32f756ig = [ "stm32-metapac/stm32f756ig" ]
427stm32f756ng = [ "stm32-metapac/stm32f756ng" ]
428stm32f756vg = [ "stm32-metapac/stm32f756vg" ]
429stm32f756zg = [ "stm32-metapac/stm32f756zg" ]
430stm32f765bg = [ "stm32-metapac/stm32f765bg" ]
431stm32f765bi = [ "stm32-metapac/stm32f765bi" ]
432stm32f765ig = [ "stm32-metapac/stm32f765ig" ]
433stm32f765ii = [ "stm32-metapac/stm32f765ii" ]
434stm32f765ng = [ "stm32-metapac/stm32f765ng" ]
435stm32f765ni = [ "stm32-metapac/stm32f765ni" ]
436stm32f765vg = [ "stm32-metapac/stm32f765vg" ]
437stm32f765vi = [ "stm32-metapac/stm32f765vi" ]
438stm32f765zg = [ "stm32-metapac/stm32f765zg" ]
439stm32f765zi = [ "stm32-metapac/stm32f765zi" ]
440stm32f767bg = [ "stm32-metapac/stm32f767bg" ]
441stm32f767bi = [ "stm32-metapac/stm32f767bi" ]
442stm32f767ig = [ "stm32-metapac/stm32f767ig" ]
443stm32f767ii = [ "stm32-metapac/stm32f767ii" ]
444stm32f767ng = [ "stm32-metapac/stm32f767ng" ]
445stm32f767ni = [ "stm32-metapac/stm32f767ni" ]
446stm32f767vg = [ "stm32-metapac/stm32f767vg" ]
447stm32f767vi = [ "stm32-metapac/stm32f767vi" ]
448stm32f767zg = [ "stm32-metapac/stm32f767zg" ]
449stm32f767zi = [ "stm32-metapac/stm32f767zi" ]
450stm32f768ai = [ "stm32-metapac/stm32f768ai" ]
451stm32f769ag = [ "stm32-metapac/stm32f769ag" ]
452stm32f769ai = [ "stm32-metapac/stm32f769ai" ]
453stm32f769bg = [ "stm32-metapac/stm32f769bg" ]
454stm32f769bi = [ "stm32-metapac/stm32f769bi" ]
455stm32f769ig = [ "stm32-metapac/stm32f769ig" ]
456stm32f769ii = [ "stm32-metapac/stm32f769ii" ]
457stm32f769ng = [ "stm32-metapac/stm32f769ng" ]
458stm32f769ni = [ "stm32-metapac/stm32f769ni" ]
459stm32f777bi = [ "stm32-metapac/stm32f777bi" ]
460stm32f777ii = [ "stm32-metapac/stm32f777ii" ]
461stm32f777ni = [ "stm32-metapac/stm32f777ni" ]
462stm32f777vi = [ "stm32-metapac/stm32f777vi" ]
463stm32f777zi = [ "stm32-metapac/stm32f777zi" ]
464stm32f778ai = [ "stm32-metapac/stm32f778ai" ]
465stm32f779ai = [ "stm32-metapac/stm32f779ai" ]
466stm32f779bi = [ "stm32-metapac/stm32f779bi" ]
467stm32f779ii = [ "stm32-metapac/stm32f779ii" ]
468stm32f779ni = [ "stm32-metapac/stm32f779ni" ]
381stm32g030c6 = [ "stm32-metapac/stm32g030c6" ] 469stm32g030c6 = [ "stm32-metapac/stm32g030c6" ]
382stm32g030c8 = [ "stm32-metapac/stm32g030c8" ] 470stm32g030c8 = [ "stm32-metapac/stm32g030c8" ]
383stm32g030f6 = [ "stm32-metapac/stm32g030f6" ] 471stm32g030f6 = [ "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")]
5mod _version; 6mod _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")]
4mod _version; 5mod _version;
5use crate::gpio::NoPin; 6use 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 @@
1pub(crate) const HSE_OSC_MIN: u32 = 4_000_000;
2pub(crate) const HSE_OSC_MAX: u32 = 26_000_000;
3pub(crate) const HSE_BYPASS_MIN: u32 = 1_000_000;
4pub(crate) const HSE_BYPASS_MAX: u32 = 50_000_000;
5
6pub(crate) const HCLK_MAX: u32 = 216_000_000;
7pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 180_000_000;
8
9pub(crate) const SYSCLK_MIN: u32 = 12_500_000;
10pub(crate) const SYSCLK_MAX: u32 = 216_000_000;
11
12pub(crate) const PCLK1_MIN: u32 = SYSCLK_MIN;
13pub(crate) const PCLK1_MAX: u32 = SYSCLK_MAX / 4;
14
15pub(crate) const PCLK2_MIN: u32 = SYSCLK_MIN;
16pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
17
18pub(crate) const PLL_48_CLK: u32 = 48_000_000;
19pub(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 @@
1mod max;
2
3use crate::pac::{FLASH, PWR, RCC};
4use crate::peripherals;
5use crate::rcc::{get_freqs, set_freqs, Clocks};
6use crate::time::Hertz;
7use core::marker::PhantomData;
8use embassy::util::Unborrow;
9
10const HSI: u32 = 16_000_000;
11
12#[non_exhaustive]
13#[derive(Default)]
14pub 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
26pub struct Rcc<'d> {
27 config: Config,
28 phantom: PhantomData<&'d mut peripherals::RCC>,
29}
30
31impl<'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
337pub 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
343struct 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")]
5mod _version; 5mod _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`
3runner = "probe-run --chip STM32F767ZITx"
4
5rustflags = [
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]
18target = "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]
2authors = ["Dario Nieuwenhuis <[email protected]>"]
3edition = "2018"
4name = "embassy-stm32f7-examples"
5version = "0.1.0"
6resolver = "2"
7
8[features]
9default = [
10 "defmt-default",
11]
12defmt-default = []
13defmt-trace = []
14defmt-debug = []
15defmt-info = []
16defmt-warn = []
17defmt-error = []
18
19[dependencies]
20embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] }
21embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] }
22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32f767zi", "unstable-pac", "time-driver-tim2"] }
23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
24
25defmt = "0.2.3"
26defmt-rtt = "0.2.0"
27
28cortex-m = "0.7.3"
29cortex-m-rt = "0.7.0"
30embedded-hal = "0.2.6"
31panic-probe = { version = "0.2.0", features = ["print-defmt"] }
32futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
33rtt-target = { version = "0.3.1", features = ["cortex-m"] }
34heapless = { version = "0.7.5", default-features = false }
35nb = "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
2use std::env;
3use std::fs::File;
4use std::io::{self, prelude::*};
5use std::path::PathBuf;
6
7#[derive(Debug)]
8enum Error {
9 Env(env::VarError),
10 Io(io::Error),
11}
12
13impl From<env::VarError> for Error {
14 fn from(error: env::VarError) -> Self {
15 Self::Env(error)
16 }
17}
18
19impl From<io::Error> for Error {
20 fn from(error: io::Error) -> Self {
21 Self::Io(error)
22 }
23}
24
25fn 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 */
2MEMORY
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"]
6mod example_common;
7use embassy::executor::Spawner;
8use embassy::time::{Duration, Timer};
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::Peripherals;
11use embedded_hal::digital::v2::OutputPin;
12use example_common::*;
13
14#[embassy::main]
15async 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"]
6mod example_common;
7use cortex_m_rt::entry;
8use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
9use embedded_hal::digital::v2::{InputPin, OutputPin};
10use example_common::*;
11
12#[entry]
13fn 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"]
6mod example_common;
7use embassy::executor::Spawner;
8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::{Input, Pull};
10use embassy_stm32::Peripherals;
11use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
12use example_common::*;
13
14#[embassy::main]
15async 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
5use defmt::info;
6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer};
8use embassy_stm32::time::Hertz;
9use embassy_stm32::Config;
10use embassy_stm32::Peripherals;
11
12#[path = "../example_common.rs"]
13mod example_common;
14
15fn 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()")]
22async 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
3use defmt_rtt as _; // global logger
4use panic_probe as _;
5
6pub use defmt::*;
7
8use core::sync::atomic::{AtomicUsize, Ordering};
9
10defmt::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
3use std::{iter::FilterMap, path::Path, slice::Iter}; 3use std::{iter::FilterMap, path::Path, slice::Iter};
4 4
5const SUPPORTED_FAMILIES: [&str; 10] = [ 5const 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",