Merge #678
678: Add minimal F2 family support r=Dirbaio a=Gekkio
Here's the bare minimum to support F2 family (207/217/205/215). A lot is missing in RCC (e.g. PLL support), but this is enough to have a working blinky example. The example is set up for a NUCLEO-F207ZG board which I don't have, but I've tested it on my custom board with a F215 and different pinout 😅
After looking at other RCC implementation, I noticed there's two main API styles: a "low-level" API (e.g. L0) where the `Config` struct has dividers and other low-level "knobs", and a "high-level" API (e.g. F0) where it has desired clock frequencies and the RCC implementation figures out how to achieve them. Which one is preferred? Personally I like the low-level API slightly more, because it gives you the most control and it would be easy to also provide some functions to calculate the required parameters based on desired clock frequencies.
F2 has a nasty errata: a delay or DSB instruction must be added after every RCC peripheral clock enable. I've added this workaround to build.rs, but am not sure if this is the best approach. Any comments?
I'm planning to add PLL support too once I know which kind of API is preferred. Would you prefer a separate pull request for that, or should I continue working on this one?
Co-authored-by: Joonas Javanainen <joonas.javanainen@gmail.com>
This commit is contained in:
commit
a211003021
2
ci.sh
2
ci.sh
@ -53,6 +53,7 @@ cargo batch \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \
|
||||
--- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \
|
||||
--- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \
|
||||
@ -63,6 +64,7 @@ cargo batch \
|
||||
--- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \
|
||||
--- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \
|
||||
--- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \
|
||||
--- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \
|
||||
--- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \
|
||||
--- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \
|
||||
--- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \
|
||||
|
@ -58,5 +58,7 @@ cargo batch \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
|
||||
--- build --release --manifest-path examples/nrf/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf --bin raw_spawn \
|
||||
--- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \
|
||||
|
@ -265,6 +265,44 @@ stm32f107rb = [ "stm32-metapac/stm32f107rb" ]
|
||||
stm32f107rc = [ "stm32-metapac/stm32f107rc" ]
|
||||
stm32f107vb = [ "stm32-metapac/stm32f107vb" ]
|
||||
stm32f107vc = [ "stm32-metapac/stm32f107vc" ]
|
||||
stm32f205rb = [ "stm32-metapac/stm32f205rb" ]
|
||||
stm32f205rc = [ "stm32-metapac/stm32f205rc" ]
|
||||
stm32f205re = [ "stm32-metapac/stm32f205re" ]
|
||||
stm32f205rf = [ "stm32-metapac/stm32f205rf" ]
|
||||
stm32f205rg = [ "stm32-metapac/stm32f205rg" ]
|
||||
stm32f205vb = [ "stm32-metapac/stm32f205vb" ]
|
||||
stm32f205vc = [ "stm32-metapac/stm32f205vc" ]
|
||||
stm32f205ve = [ "stm32-metapac/stm32f205ve" ]
|
||||
stm32f205vf = [ "stm32-metapac/stm32f205vf" ]
|
||||
stm32f205vg = [ "stm32-metapac/stm32f205vg" ]
|
||||
stm32f205zc = [ "stm32-metapac/stm32f205zc" ]
|
||||
stm32f205ze = [ "stm32-metapac/stm32f205ze" ]
|
||||
stm32f205zf = [ "stm32-metapac/stm32f205zf" ]
|
||||
stm32f205zg = [ "stm32-metapac/stm32f205zg" ]
|
||||
stm32f207ic = [ "stm32-metapac/stm32f207ic" ]
|
||||
stm32f207ie = [ "stm32-metapac/stm32f207ie" ]
|
||||
stm32f207if = [ "stm32-metapac/stm32f207if" ]
|
||||
stm32f207ig = [ "stm32-metapac/stm32f207ig" ]
|
||||
stm32f207vc = [ "stm32-metapac/stm32f207vc" ]
|
||||
stm32f207ve = [ "stm32-metapac/stm32f207ve" ]
|
||||
stm32f207vf = [ "stm32-metapac/stm32f207vf" ]
|
||||
stm32f207vg = [ "stm32-metapac/stm32f207vg" ]
|
||||
stm32f207zc = [ "stm32-metapac/stm32f207zc" ]
|
||||
stm32f207ze = [ "stm32-metapac/stm32f207ze" ]
|
||||
stm32f207zf = [ "stm32-metapac/stm32f207zf" ]
|
||||
stm32f207zg = [ "stm32-metapac/stm32f207zg" ]
|
||||
stm32f215re = [ "stm32-metapac/stm32f215re" ]
|
||||
stm32f215rg = [ "stm32-metapac/stm32f215rg" ]
|
||||
stm32f215ve = [ "stm32-metapac/stm32f215ve" ]
|
||||
stm32f215vg = [ "stm32-metapac/stm32f215vg" ]
|
||||
stm32f215ze = [ "stm32-metapac/stm32f215ze" ]
|
||||
stm32f215zg = [ "stm32-metapac/stm32f215zg" ]
|
||||
stm32f217ie = [ "stm32-metapac/stm32f217ie" ]
|
||||
stm32f217ig = [ "stm32-metapac/stm32f217ig" ]
|
||||
stm32f217ve = [ "stm32-metapac/stm32f217ve" ]
|
||||
stm32f217vg = [ "stm32-metapac/stm32f217vg" ]
|
||||
stm32f217ze = [ "stm32-metapac/stm32f217ze" ]
|
||||
stm32f217zg = [ "stm32-metapac/stm32f217zg" ]
|
||||
stm32f301c6 = [ "stm32-metapac/stm32f301c6" ]
|
||||
stm32f301c8 = [ "stm32-metapac/stm32f301c8" ]
|
||||
stm32f301k6 = [ "stm32-metapac/stm32f301k6" ]
|
||||
|
@ -166,6 +166,15 @@ fn main() {
|
||||
None => TokenStream::new(),
|
||||
};
|
||||
|
||||
let after_enable = if chip_name.starts_with("stm32f2") {
|
||||
// Errata: ES0005 - 2.1.11 Delay after an RCC peripheral clock enabling
|
||||
quote! {
|
||||
cortex_m::asm::dsb();
|
||||
}
|
||||
} else {
|
||||
TokenStream::new()
|
||||
};
|
||||
|
||||
let pname = format_ident!("{}", p.name);
|
||||
let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
|
||||
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
|
||||
@ -180,7 +189,8 @@ fn main() {
|
||||
}
|
||||
fn enable() {
|
||||
critical_section::with(|_| unsafe {
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true))
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
||||
#after_enable
|
||||
})
|
||||
}
|
||||
fn disable() {
|
||||
|
303
embassy-stm32/src/rcc/f2.rs
Normal file
303
embassy-stm32/src/rcc/f2.rs
Normal file
@ -0,0 +1,303 @@
|
||||
use core::ops::Div;
|
||||
|
||||
use crate::pac::flash::vals::Latency;
|
||||
use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
|
||||
use crate::pac::{FLASH, RCC};
|
||||
use crate::rcc::{set_freqs, Clocks};
|
||||
use crate::time::Hertz;
|
||||
|
||||
/// HSI speed
|
||||
pub const HSI: Hertz = Hertz(16_000_000);
|
||||
|
||||
/// System clock mux source
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ClockSrc {
|
||||
HSE(Hertz, HSESrc),
|
||||
HSI,
|
||||
}
|
||||
|
||||
/// HSE clock source
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum HSESrc {
|
||||
/// Crystal/ceramic resonator
|
||||
Crystal,
|
||||
/// External clock source, HSE bypassed
|
||||
Bypass,
|
||||
}
|
||||
|
||||
/// AHB prescaler
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum AHBPrescaler {
|
||||
NotDivided,
|
||||
Div2,
|
||||
Div4,
|
||||
Div8,
|
||||
Div16,
|
||||
Div64,
|
||||
Div128,
|
||||
Div256,
|
||||
Div512,
|
||||
}
|
||||
|
||||
impl Div<AHBPrescaler> for Hertz {
|
||||
type Output = Hertz;
|
||||
|
||||
fn div(self, rhs: AHBPrescaler) -> Self::Output {
|
||||
let divisor = match rhs {
|
||||
AHBPrescaler::NotDivided => 1,
|
||||
AHBPrescaler::Div2 => 2,
|
||||
AHBPrescaler::Div4 => 4,
|
||||
AHBPrescaler::Div8 => 8,
|
||||
AHBPrescaler::Div16 => 16,
|
||||
AHBPrescaler::Div64 => 64,
|
||||
AHBPrescaler::Div128 => 128,
|
||||
AHBPrescaler::Div256 => 256,
|
||||
AHBPrescaler::Div512 => 512,
|
||||
};
|
||||
Hertz(self.0 / divisor)
|
||||
}
|
||||
}
|
||||
|
||||
/// APB prescaler
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum APBPrescaler {
|
||||
NotDivided,
|
||||
Div2,
|
||||
Div4,
|
||||
Div8,
|
||||
Div16,
|
||||
}
|
||||
|
||||
impl Div<APBPrescaler> for Hertz {
|
||||
type Output = Hertz;
|
||||
|
||||
fn div(self, rhs: APBPrescaler) -> Self::Output {
|
||||
let divisor = match rhs {
|
||||
APBPrescaler::NotDivided => 1,
|
||||
APBPrescaler::Div2 => 2,
|
||||
APBPrescaler::Div4 => 4,
|
||||
APBPrescaler::Div8 => 8,
|
||||
APBPrescaler::Div16 => 16,
|
||||
};
|
||||
Hertz(self.0 / divisor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Ppre> for APBPrescaler {
|
||||
fn into(self) -> Ppre {
|
||||
match self {
|
||||
APBPrescaler::NotDivided => Ppre::DIV1,
|
||||
APBPrescaler::Div2 => Ppre::DIV2,
|
||||
APBPrescaler::Div4 => Ppre::DIV4,
|
||||
APBPrescaler::Div8 => Ppre::DIV8,
|
||||
APBPrescaler::Div16 => Ppre::DIV16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Hpre> for AHBPrescaler {
|
||||
fn into(self) -> Hpre {
|
||||
match self {
|
||||
AHBPrescaler::NotDivided => Hpre::DIV1,
|
||||
AHBPrescaler::Div2 => Hpre::DIV2,
|
||||
AHBPrescaler::Div4 => Hpre::DIV4,
|
||||
AHBPrescaler::Div8 => Hpre::DIV8,
|
||||
AHBPrescaler::Div16 => Hpre::DIV16,
|
||||
AHBPrescaler::Div64 => Hpre::DIV64,
|
||||
AHBPrescaler::Div128 => Hpre::DIV128,
|
||||
AHBPrescaler::Div256 => Hpre::DIV256,
|
||||
AHBPrescaler::Div512 => Hpre::DIV512,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Voltage Range
|
||||
///
|
||||
/// Represents the system supply voltage range
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum VoltageRange {
|
||||
/// 1.8 to 3.6 V
|
||||
Min1V8,
|
||||
/// 2.1 to 3.6 V
|
||||
Min2V1,
|
||||
/// 2.4 to 3.6 V
|
||||
Min2V4,
|
||||
/// 2.7 to 3.6 V
|
||||
Min2V7,
|
||||
}
|
||||
|
||||
impl VoltageRange {
|
||||
const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
|
||||
let ahb_freq = ahb_freq.0;
|
||||
// Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
|
||||
// frequency
|
||||
match self {
|
||||
VoltageRange::Min1V8 => {
|
||||
if ahb_freq <= 16_000_000 {
|
||||
Some(Latency::WS0)
|
||||
} else if ahb_freq <= 32_000_000 {
|
||||
Some(Latency::WS1)
|
||||
} else if ahb_freq <= 48_000_000 {
|
||||
Some(Latency::WS2)
|
||||
} else if ahb_freq <= 64_000_000 {
|
||||
Some(Latency::WS3)
|
||||
} else if ahb_freq <= 80_000_000 {
|
||||
Some(Latency::WS4)
|
||||
} else if ahb_freq <= 96_000_000 {
|
||||
Some(Latency::WS5)
|
||||
} else if ahb_freq <= 112_000_000 {
|
||||
Some(Latency::WS6)
|
||||
} else if ahb_freq <= 120_000_000 {
|
||||
Some(Latency::WS7)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
VoltageRange::Min2V1 => {
|
||||
if ahb_freq <= 18_000_000 {
|
||||
Some(Latency::WS0)
|
||||
} else if ahb_freq <= 36_000_000 {
|
||||
Some(Latency::WS1)
|
||||
} else if ahb_freq <= 54_000_000 {
|
||||
Some(Latency::WS2)
|
||||
} else if ahb_freq <= 72_000_000 {
|
||||
Some(Latency::WS3)
|
||||
} else if ahb_freq <= 90_000_000 {
|
||||
Some(Latency::WS4)
|
||||
} else if ahb_freq <= 108_000_000 {
|
||||
Some(Latency::WS5)
|
||||
} else if ahb_freq <= 120_000_000 {
|
||||
Some(Latency::WS6)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
VoltageRange::Min2V4 => {
|
||||
if ahb_freq <= 24_000_000 {
|
||||
Some(Latency::WS0)
|
||||
} else if ahb_freq <= 48_000_000 {
|
||||
Some(Latency::WS1)
|
||||
} else if ahb_freq <= 72_000_000 {
|
||||
Some(Latency::WS2)
|
||||
} else if ahb_freq <= 96_000_000 {
|
||||
Some(Latency::WS3)
|
||||
} else if ahb_freq <= 120_000_000 {
|
||||
Some(Latency::WS4)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
VoltageRange::Min2V7 => {
|
||||
if ahb_freq <= 30_000_000 {
|
||||
Some(Latency::WS0)
|
||||
} else if ahb_freq <= 60_000_000 {
|
||||
Some(Latency::WS1)
|
||||
} else if ahb_freq <= 90_000_000 {
|
||||
Some(Latency::WS2)
|
||||
} else if ahb_freq <= 120_000_000 {
|
||||
Some(Latency::WS3)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clocks configuration
|
||||
pub struct Config {
|
||||
pub mux: ClockSrc,
|
||||
pub voltage: VoltageRange,
|
||||
pub ahb_pre: AHBPrescaler,
|
||||
pub apb1_pre: APBPrescaler,
|
||||
pub apb2_pre: APBPrescaler,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
#[inline]
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
voltage: VoltageRange::Min1V8,
|
||||
mux: ClockSrc::HSI,
|
||||
ahb_pre: AHBPrescaler::NotDivided,
|
||||
apb1_pre: APBPrescaler::NotDivided,
|
||||
apb2_pre: APBPrescaler::NotDivided,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn enable_hse(source: HSESrc) {
|
||||
RCC.cr().write(|w| {
|
||||
w.set_hsebyp(match source {
|
||||
HSESrc::Bypass => true,
|
||||
HSESrc::Crystal => false,
|
||||
});
|
||||
w.set_hseon(true)
|
||||
});
|
||||
while !RCC.cr().read().hserdy() {}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init(config: Config) {
|
||||
let (sys_clk, sw) = match config.mux {
|
||||
ClockSrc::HSI => {
|
||||
// Enable HSI
|
||||
RCC.cr().write(|w| w.set_hsion(true));
|
||||
while !RCC.cr().read().hsirdy() {}
|
||||
|
||||
(HSI, Sw::HSI)
|
||||
}
|
||||
ClockSrc::HSE(freq, source) => {
|
||||
enable_hse(source);
|
||||
(freq, Sw::HSE)
|
||||
}
|
||||
};
|
||||
// RM0033 Figure 9. Clock tree suggests max SYSCLK/HCLK is 168 MHz, but datasheet specifies PLL
|
||||
// max output to be 120 MHz, so there's no way to get higher frequencies
|
||||
assert!(sys_clk <= Hertz(120_000_000));
|
||||
|
||||
let ahb_freq = sys_clk / config.ahb_pre;
|
||||
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
|
||||
assert!(ahb_freq <= Hertz(120_000_000));
|
||||
|
||||
let flash_ws = config.voltage.wait_states(ahb_freq).expect("Invalid HCLK");
|
||||
FLASH.acr().modify(|w| w.set_latency(flash_ws));
|
||||
|
||||
RCC.cfgr().modify(|w| {
|
||||
w.set_sw(sw.into());
|
||||
w.set_hpre(config.ahb_pre.into());
|
||||
w.set_ppre1(config.apb1_pre.into());
|
||||
w.set_ppre2(config.apb2_pre.into());
|
||||
});
|
||||
|
||||
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
|
||||
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
|
||||
pre => {
|
||||
let freq = ahb_freq / pre;
|
||||
(freq, Hertz(freq.0 * 2))
|
||||
}
|
||||
};
|
||||
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
|
||||
assert!(apb1_freq <= Hertz(30_000_000));
|
||||
|
||||
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
|
||||
APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
|
||||
pre => {
|
||||
let freq = ahb_freq / pre;
|
||||
(freq, Hertz(freq.0 * 2))
|
||||
}
|
||||
};
|
||||
// Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
|
||||
assert!(apb2_freq <= Hertz(60_000_000));
|
||||
|
||||
set_freqs(Clocks {
|
||||
sys: sys_clk,
|
||||
ahb1: ahb_freq,
|
||||
ahb2: ahb_freq,
|
||||
ahb3: ahb_freq,
|
||||
apb1: apb1_freq,
|
||||
apb1_tim: apb1_tim_freq,
|
||||
apb2: apb2_freq,
|
||||
apb2_tim: apb2_tim_freq,
|
||||
});
|
||||
}
|
@ -5,6 +5,7 @@ use core::mem::MaybeUninit;
|
||||
|
||||
#[cfg_attr(rcc_f0, path = "f0.rs")]
|
||||
#[cfg_attr(rcc_f1, path = "f1.rs")]
|
||||
#[cfg_attr(rcc_f2, path = "f2.rs")]
|
||||
#[cfg_attr(rcc_f3, path = "f3.rs")]
|
||||
#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")]
|
||||
#[cfg_attr(rcc_f7, path = "f7.rs")]
|
||||
@ -39,11 +40,11 @@ pub struct Clocks {
|
||||
// AHB
|
||||
pub ahb1: Hertz,
|
||||
#[cfg(any(
|
||||
rcc_l4, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, rcc_wl5
|
||||
rcc_l4, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, rcc_wl5
|
||||
))]
|
||||
pub ahb2: Hertz,
|
||||
#[cfg(any(
|
||||
rcc_l4, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5
|
||||
rcc_l4, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5
|
||||
))]
|
||||
pub ahb3: Hertz,
|
||||
#[cfg(any(rcc_h7, rcc_h7ab))]
|
||||
|
6
examples/stm32f2/.cargo/config
Normal file
6
examples/stm32f2/.cargo/config
Normal file
@ -0,0 +1,6 @@
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
# replace STM32F207ZGTx with your chip as listed in `probe-run --list-chips`
|
||||
runner = "probe-run --chip STM32F207ZGTx"
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
21
examples/stm32f2/Cargo.toml
Normal file
21
examples/stm32f2/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"]
|
||||
edition = "2018"
|
||||
name = "embassy-stm32f2-examples"
|
||||
version = "0.1.0"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
||||
|
||||
defmt = "0.3"
|
||||
defmt-rtt = "0.3"
|
||||
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.7.5", default-features = false }
|
||||
nb = "1.0.0"
|
5
examples/stm32f2/build.rs
Normal file
5
examples/stm32f2/build.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
println!("cargo:rustc-link-arg-bins=--nmagic");
|
||||
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
||||
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
||||
}
|
29
examples/stm32f2/src/bin/blinky.rs
Normal file
29
examples/stm32f2/src/bin/blinky.rs
Normal file
@ -0,0 +1,29 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
#[path = "../example_common.rs"]
|
||||
mod example_common;
|
||||
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::Peripherals;
|
||||
use example_common::*;
|
||||
|
||||
#[embassy::main]
|
||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
info!("Hello World!");
|
||||
|
||||
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
||||
|
||||
loop {
|
||||
info!("high");
|
||||
led.set_high();
|
||||
Timer::after(Duration::from_millis(1000)).await;
|
||||
|
||||
info!("low");
|
||||
led.set_low();
|
||||
Timer::after(Duration::from_millis(1000)).await;
|
||||
}
|
||||
}
|
19
examples/stm32f2/src/example_common.rs
Normal file
19
examples/stm32f2/src/example_common.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![macro_use]
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
use panic_probe as _;
|
||||
|
||||
pub use defmt::*;
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
defmt::timestamp! {
|
||||
"{=u64}",
|
||||
{
|
||||
static COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
// NOTE(no-CAS) `timestamps` runs with interrupts disabled
|
||||
let n = COUNT.load(Ordering::Relaxed);
|
||||
COUNT.store(n + 1, Ordering::Relaxed);
|
||||
n as u64
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use std::{iter::FilterMap, path::Path, slice::Iter};
|
||||
const SUPPORTED_FAMILIES: &[&str] = &[
|
||||
"stm32f0",
|
||||
"stm32f1",
|
||||
"stm32f2",
|
||||
"stm32f3",
|
||||
"stm32f4",
|
||||
"stm32f7",
|
||||
@ -52,7 +53,7 @@ impl FilterSupported for &[(String, Vec<String>)] {
|
||||
///
|
||||
/// This function is slow because all the yaml files are parsed.
|
||||
pub fn chip_names_and_cores() -> Vec<(String, Vec<String>)> {
|
||||
glob::glob("../stm32-data/data/chips/*.yaml")
|
||||
glob::glob("../stm32-data/data/chips/*.json")
|
||||
.unwrap()
|
||||
.filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok())
|
||||
.filter_map(|entry| {
|
||||
|
Loading…
Reference in New Issue
Block a user