mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
Merge pull request #2898 from embassy-rs/h7rs
stm32: add support for STM32H7[RS] "bootflash line", add HIL tests.
This commit is contained in:
commit
318425040a
6
ci.sh
6
ci.sh
@ -125,6 +125,10 @@ cargo batch \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r3z8,defmt,exti,time-driver-tim1,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7r7a8,defmt,exti,time-driver-tim1,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3a8,defmt,exti,time-driver-tim1,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s7z8,defmt,exti,time-driver-tim1,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
|
||||
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \
|
||||
@ -189,6 +193,7 @@ cargo batch \
|
||||
--- build --release --manifest-path examples/stm32g4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32g4 \
|
||||
--- build --release --manifest-path examples/stm32h5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32h5 \
|
||||
--- build --release --manifest-path examples/stm32h7/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32h7 \
|
||||
--- build --release --manifest-path examples/stm32h7rs/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32h7rs \
|
||||
--- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32l0 \
|
||||
--- build --release --manifest-path examples/stm32l1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32l1 \
|
||||
--- build --release --manifest-path examples/stm32l4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32l4 \
|
||||
@ -240,6 +245,7 @@ cargo batch \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --out-dir out/tests/stm32f303ze \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --out-dir out/tests/stm32l496zg \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --out-dir out/tests/stm32wl55jc \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7s3l8 --out-dir out/tests/stm32h7s3l8 \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32f091rc --out-dir out/tests/stm32f091rc \
|
||||
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb --out-dir out/tests/stm32h503rb \
|
||||
--- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/tests/rpi-pico \
|
||||
|
@ -72,7 +72,7 @@ rand_core = "0.6.3"
|
||||
sdio-host = "0.5.0"
|
||||
critical-section = "1.1"
|
||||
#stm32-metapac = { version = "15" }
|
||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-37a0941112fd16fee53aaa2005fd67b77adab59c" }
|
||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-afee4331adc717f4cc52caab16838c95334535be" }
|
||||
|
||||
vcell = "0.1.3"
|
||||
nb = "1.0.0"
|
||||
@ -98,7 +98,7 @@ proc-macro2 = "1.0.36"
|
||||
quote = "1.0.15"
|
||||
|
||||
#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
|
||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-37a0941112fd16fee53aaa2005fd67b77adab59c", default-features = false, features = ["metadata"]}
|
||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-afee4331adc717f4cc52caab16838c95334535be", default-features = false, features = ["metadata"]}
|
||||
|
||||
[features]
|
||||
default = ["rt"]
|
||||
@ -1095,6 +1095,26 @@ stm32h7b3qi = [ "stm32-metapac/stm32h7b3qi" ]
|
||||
stm32h7b3ri = [ "stm32-metapac/stm32h7b3ri" ]
|
||||
stm32h7b3vi = [ "stm32-metapac/stm32h7b3vi" ]
|
||||
stm32h7b3zi = [ "stm32-metapac/stm32h7b3zi" ]
|
||||
stm32h7r3a8 = [ "stm32-metapac/stm32h7r3a8" ]
|
||||
stm32h7r3i8 = [ "stm32-metapac/stm32h7r3i8" ]
|
||||
stm32h7r3l8 = [ "stm32-metapac/stm32h7r3l8" ]
|
||||
stm32h7r3r8 = [ "stm32-metapac/stm32h7r3r8" ]
|
||||
stm32h7r3v8 = [ "stm32-metapac/stm32h7r3v8" ]
|
||||
stm32h7r3z8 = [ "stm32-metapac/stm32h7r3z8" ]
|
||||
stm32h7r7a8 = [ "stm32-metapac/stm32h7r7a8" ]
|
||||
stm32h7r7i8 = [ "stm32-metapac/stm32h7r7i8" ]
|
||||
stm32h7r7l8 = [ "stm32-metapac/stm32h7r7l8" ]
|
||||
stm32h7r7z8 = [ "stm32-metapac/stm32h7r7z8" ]
|
||||
stm32h7s3a8 = [ "stm32-metapac/stm32h7s3a8" ]
|
||||
stm32h7s3i8 = [ "stm32-metapac/stm32h7s3i8" ]
|
||||
stm32h7s3l8 = [ "stm32-metapac/stm32h7s3l8" ]
|
||||
stm32h7s3r8 = [ "stm32-metapac/stm32h7s3r8" ]
|
||||
stm32h7s3v8 = [ "stm32-metapac/stm32h7s3v8" ]
|
||||
stm32h7s3z8 = [ "stm32-metapac/stm32h7s3z8" ]
|
||||
stm32h7s7a8 = [ "stm32-metapac/stm32h7s7a8" ]
|
||||
stm32h7s7i8 = [ "stm32-metapac/stm32h7s7i8" ]
|
||||
stm32h7s7l8 = [ "stm32-metapac/stm32h7s7l8" ]
|
||||
stm32h7s7z8 = [ "stm32-metapac/stm32h7s7z8" ]
|
||||
stm32l010c6 = [ "stm32-metapac/stm32l010c6" ]
|
||||
stm32l010f4 = [ "stm32-metapac/stm32l010f4" ]
|
||||
stm32l010k4 = [ "stm32-metapac/stm32l010k4" ]
|
||||
|
@ -406,7 +406,16 @@ fn main() {
|
||||
},
|
||||
);
|
||||
}
|
||||
if chip_name.starts_with("stm32h7") {
|
||||
|
||||
if chip_name.starts_with("stm32h7r") || chip_name.starts_with("stm32h7s") {
|
||||
clock_gen.chained_muxes.insert(
|
||||
"PER",
|
||||
&PeripheralRccRegister {
|
||||
register: "AHBPERCKSELR",
|
||||
field: "PERSEL",
|
||||
},
|
||||
);
|
||||
} else if chip_name.starts_with("stm32h7") {
|
||||
clock_gen.chained_muxes.insert(
|
||||
"PER",
|
||||
&PeripheralRccRegister {
|
||||
@ -1585,7 +1594,11 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=package_{}", &chip_name[10..11]);
|
||||
println!("cargo:rustc-cfg=flashsize_{}", &chip_name[11..12]);
|
||||
} else {
|
||||
println!("cargo:rustc-cfg={}", &chip_name[..7]); // stm32f4
|
||||
if &chip_name[..8] == "stm32h7r" || &chip_name[..8] == "stm32h7s" {
|
||||
println!("cargo:rustc-cfg=stm32h7rs");
|
||||
} else {
|
||||
println!("cargo:rustc-cfg={}", &chip_name[..7]); // stm32f4
|
||||
}
|
||||
println!("cargo:rustc-cfg={}", &chip_name[..9]); // stm32f429
|
||||
println!("cargo:rustc-cfg={}x", &chip_name[..8]); // stm32f42x
|
||||
println!("cargo:rustc-cfg={}x{}", &chip_name[..7], &chip_name[8..9]); // stm32f4x9
|
||||
|
@ -30,10 +30,10 @@ impl Registers {
|
||||
&mut self.msg_ram_mut().transmit.tbsa[bufidx]
|
||||
}
|
||||
pub fn msg_ram_mut(&self) -> &mut RegisterBlock {
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
let ptr = self.msgram.ram(self.msg_ram_offset / 4).as_ptr() as *mut RegisterBlock;
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
let ptr = self.msgram.as_ptr() as *mut RegisterBlock;
|
||||
|
||||
unsafe { &mut (*ptr) }
|
||||
@ -105,7 +105,7 @@ impl Registers {
|
||||
return Some(BusError::BusWarning);
|
||||
} else {
|
||||
cfg_if! {
|
||||
if #[cfg(stm32h7)] {
|
||||
if #[cfg(can_fdcan_h7)] {
|
||||
let lec = err.lec();
|
||||
} else {
|
||||
let lec = err.lec().to_bits();
|
||||
@ -334,14 +334,14 @@ impl Registers {
|
||||
// set extended filters list size to 8
|
||||
// REQUIRED: we use the memory map as if these settings are set
|
||||
// instead of re-calculating them.
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
{
|
||||
self.regs.rxgfc().modify(|w| {
|
||||
w.set_lss(crate::can::fd::message_ram::STANDARD_FILTER_MAX);
|
||||
w.set_lse(crate::can::fd::message_ram::EXTENDED_FILTER_MAX);
|
||||
});
|
||||
}
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
{
|
||||
self.regs
|
||||
.sidfc()
|
||||
@ -354,11 +354,11 @@ impl Registers {
|
||||
self.configure_msg_ram();
|
||||
|
||||
// Enable timestamping
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
self.regs
|
||||
.tscc()
|
||||
.write(|w| w.set_tss(stm32_metapac::can::vals::Tss::INCREMENT));
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
self.regs.tscc().write(|w| w.set_tss(0x01));
|
||||
|
||||
// this isn't really documented in the reference manual
|
||||
@ -491,9 +491,9 @@ impl Registers {
|
||||
|
||||
self.regs.cccr().modify(|w| {
|
||||
w.set_fdoe(fdoe);
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
w.set_bse(brse);
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
w.set_brse(brse);
|
||||
});
|
||||
}
|
||||
@ -508,14 +508,14 @@ impl Registers {
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) {
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
let (tcp, tss) = match select {
|
||||
TimestampSource::None => (0, 0),
|
||||
TimestampSource::Prescaler(p) => (p as u8, 1),
|
||||
TimestampSource::FromTIM3 => (0, 2),
|
||||
};
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
let (tcp, tss) = match select {
|
||||
TimestampSource::None => (0, stm32_metapac::can::vals::Tss::ZERO),
|
||||
TimestampSource::Prescaler(p) => (p as u8, stm32_metapac::can::vals::Tss::INCREMENT),
|
||||
@ -528,7 +528,7 @@ impl Registers {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
/// Configures the global filter settings
|
||||
#[inline]
|
||||
pub fn set_global_filter(&mut self, filter: GlobalFilter) {
|
||||
@ -551,7 +551,7 @@ impl Registers {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
/// Configures the global filter settings
|
||||
#[inline]
|
||||
pub fn set_global_filter(&mut self, filter: GlobalFilter) {
|
||||
@ -575,10 +575,10 @@ impl Registers {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
fn configure_msg_ram(&mut self) {}
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
fn configure_msg_ram(&mut self) {
|
||||
let r = self.regs;
|
||||
|
||||
|
@ -975,7 +975,7 @@ macro_rules! impl_fdcan {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
#[cfg(not(can_fdcan_h7))]
|
||||
foreach_peripheral!(
|
||||
(can, FDCAN) => { impl_fdcan!(FDCAN, FDCANRAM); };
|
||||
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM1); };
|
||||
@ -983,7 +983,7 @@ foreach_peripheral!(
|
||||
(can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM3); };
|
||||
);
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(can_fdcan_h7)]
|
||||
foreach_peripheral!(
|
||||
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM, 0x0000); };
|
||||
(can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM, 0x0C00); };
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! Crypto Accelerator (CRYP)
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
use core::cmp::min;
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr;
|
||||
@ -7,7 +7,7 @@ use core::ptr;
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use crate::dma::{NoDma, Priority, Transfer, TransferOptions};
|
||||
use crate::dma::{NoDma, Transfer, TransferOptions};
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::{interrupt, pac, peripherals, Peripheral};
|
||||
|
||||
@ -147,7 +147,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for TdesEcb<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(0));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(0));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -189,7 +189,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for TdesCbc<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(1));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(1));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -231,7 +231,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for DesEcb<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(2));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(2));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -272,7 +272,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for DesCbc<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(3));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(3));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -313,7 +313,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesEcb<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(7));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(7));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -327,7 +327,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesEcb<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(2));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(2));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -370,7 +370,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCbc<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(7));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(7));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -384,7 +384,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCbc<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(5));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(5));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -426,7 +426,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesCtr<'c, KEY_SIZE> {
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode(6));
|
||||
}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
p.cr().modify(|w| w.set_algomode0(6));
|
||||
p.cr().modify(|w| w.set_algomode3(false));
|
||||
@ -439,14 +439,14 @@ impl<'c> CipherSized for AesCtr<'c, { 192 / 8 }> {}
|
||||
impl<'c> CipherSized for AesCtr<'c, { 256 / 8 }> {}
|
||||
impl<'c, const KEY_SIZE: usize> IVSized for AesCtr<'c, KEY_SIZE> {}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
///AES-GCM Cipher Mode
|
||||
pub struct AesGcm<'c, const KEY_SIZE: usize> {
|
||||
iv: [u8; 16],
|
||||
key: &'c [u8; KEY_SIZE],
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> AesGcm<'c, KEY_SIZE> {
|
||||
/// Constucts a new AES-GCM cipher for a cryptographic operation.
|
||||
pub fn new(key: &'c [u8; KEY_SIZE], iv: &'c [u8; 12]) -> Self {
|
||||
@ -457,7 +457,7 @@ impl<'c, const KEY_SIZE: usize> AesGcm<'c, KEY_SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> {
|
||||
const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
|
||||
|
||||
@ -504,7 +504,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> {
|
||||
[0; 4]
|
||||
}
|
||||
|
||||
#[cfg(cryp_v3)]
|
||||
#[cfg(any(cryp_v3, cryp_v4))]
|
||||
fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] {
|
||||
//Handle special GCM partial block process.
|
||||
p.cr().modify(|w| w.set_npblb(padding_len as u8));
|
||||
@ -573,25 +573,25 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGcm<'c, { 128 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGcm<'c, { 192 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGcm<'c, { 256 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> CipherAuthenticated<16> for AesGcm<'c, KEY_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> IVSized for AesGcm<'c, KEY_SIZE> {}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
/// AES-GMAC Cipher Mode
|
||||
pub struct AesGmac<'c, const KEY_SIZE: usize> {
|
||||
iv: [u8; 16],
|
||||
key: &'c [u8; KEY_SIZE],
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> AesGmac<'c, KEY_SIZE> {
|
||||
/// Constructs a new AES-GMAC cipher for a cryptographic operation.
|
||||
pub fn new(key: &'c [u8; KEY_SIZE], iv: &'c [u8; 12]) -> Self {
|
||||
@ -602,7 +602,7 @@ impl<'c, const KEY_SIZE: usize> AesGmac<'c, KEY_SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> {
|
||||
const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
|
||||
|
||||
@ -649,7 +649,7 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> {
|
||||
[0; 4]
|
||||
}
|
||||
|
||||
#[cfg(cryp_v3)]
|
||||
#[cfg(any(cryp_v3, cryp_v4))]
|
||||
fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] {
|
||||
//Handle special GCM partial block process.
|
||||
p.cr().modify(|w| w.set_npblb(padding_len as u8));
|
||||
@ -716,18 +716,18 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGmac<'c, { 128 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGmac<'c, { 192 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c> CipherSized for AesGmac<'c, { 256 / 8 }> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> CipherAuthenticated<16> for AesGmac<'c, KEY_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize> IVSized for AesGmac<'c, KEY_SIZE> {}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
/// AES-CCM Cipher Mode
|
||||
pub struct AesCcm<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> {
|
||||
key: &'c [u8; KEY_SIZE],
|
||||
@ -737,7 +737,7 @@ pub struct AesCcm<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZ
|
||||
ctr: [u8; 16],
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> AesCcm<'c, KEY_SIZE, TAG_SIZE, IV_SIZE> {
|
||||
/// Constructs a new AES-CCM cipher for a cryptographic operation.
|
||||
pub fn new(key: &'c [u8; KEY_SIZE], iv: &'c [u8; IV_SIZE], aad_len: usize, payload_len: usize) -> Self {
|
||||
@ -801,7 +801,7 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Aes
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cipher<'c>
|
||||
for AesCcm<'c, KEY_SIZE, TAG_SIZE, IV_SIZE>
|
||||
{
|
||||
@ -865,7 +865,7 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip
|
||||
return temp1;
|
||||
}
|
||||
|
||||
#[cfg(cryp_v3)]
|
||||
#[cfg(any(cryp_v3, cryp_v4))]
|
||||
fn pre_final(&self, p: &pac::cryp::Cryp, _dir: Direction, padding_len: usize) -> [u32; 4] {
|
||||
//Handle special GCM partial block process.
|
||||
p.cr().modify(|w| w.set_npblb(padding_len as u8));
|
||||
@ -950,39 +950,39 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const TAG_SIZE: usize, const IV_SIZE: usize> CipherSized for AesCcm<'c, { 128 / 8 }, TAG_SIZE, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const TAG_SIZE: usize, const IV_SIZE: usize> CipherSized for AesCcm<'c, { 192 / 8 }, TAG_SIZE, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const TAG_SIZE: usize, const IV_SIZE: usize> CipherSized for AesCcm<'c, { 256 / 8 }, TAG_SIZE, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<4> for AesCcm<'c, KEY_SIZE, 4, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<6> for AesCcm<'c, KEY_SIZE, 6, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<8> for AesCcm<'c, KEY_SIZE, 8, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<10> for AesCcm<'c, KEY_SIZE, 10, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<12> for AesCcm<'c, KEY_SIZE, 12, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<14> for AesCcm<'c, KEY_SIZE, 14, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const IV_SIZE: usize> CipherAuthenticated<16> for AesCcm<'c, KEY_SIZE, 16, IV_SIZE> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 7> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 8> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 9> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 10> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 11> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 12> {}
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize> IVSized for AesCcm<'c, KEY_SIZE, TAG_SIZE, 13> {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -1205,7 +1205,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
ctx
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
/// Controls the header phase of cipher processing.
|
||||
/// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC.
|
||||
/// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload_blocking`.
|
||||
@ -1302,7 +1302,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
self.store_context(ctx);
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
/// Controls the header phase of cipher processing.
|
||||
/// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC.
|
||||
/// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload`.
|
||||
@ -1420,7 +1420,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
if !ctx.aad_complete && ctx.header_len > 0 {
|
||||
panic!("Additional associated data must be processed first!");
|
||||
} else if !ctx.aad_complete {
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
ctx.aad_complete = true;
|
||||
T::regs().cr().modify(|w| w.set_crypen(false));
|
||||
@ -1512,7 +1512,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
if !ctx.aad_complete && ctx.header_len > 0 {
|
||||
panic!("Additional associated data must be processed first!");
|
||||
} else if !ctx.aad_complete {
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
{
|
||||
ctx.aad_complete = true;
|
||||
T::regs().cr().modify(|w| w.set_crypen(false));
|
||||
@ -1585,7 +1585,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
self.store_context(ctx);
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
/// Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC.
|
||||
/// Called after the all data has been encrypted/decrypted by `payload`.
|
||||
pub fn finish_blocking<
|
||||
@ -1614,7 +1614,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
payloadlen1.swap_bytes(),
|
||||
payloadlen2.swap_bytes(),
|
||||
];
|
||||
#[cfg(cryp_v3)]
|
||||
#[cfg(any(cryp_v3, cryp_v4))]
|
||||
let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2];
|
||||
|
||||
self.write_words_blocking(C::BLOCK_SIZE, &footer);
|
||||
@ -1631,7 +1631,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
tag
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
// Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC.
|
||||
/// Called after the all data has been encrypted/decrypted by `payload`.
|
||||
pub async fn finish<
|
||||
@ -1664,7 +1664,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
payloadlen1.swap_bytes(),
|
||||
payloadlen2.swap_bytes(),
|
||||
];
|
||||
#[cfg(cryp_v3)]
|
||||
#[cfg(any(cryp_v3, cryp_v4))]
|
||||
let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2];
|
||||
|
||||
let write = Self::write_words(&mut self.indma, C::BLOCK_SIZE, &footer);
|
||||
@ -1735,7 +1735,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
ctx.iv[2] = T::regs().init(1).ivlr().read();
|
||||
ctx.iv[3] = T::regs().init(1).ivrr().read();
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
for i in 0..8 {
|
||||
ctx.csgcmccm[i] = T::regs().csgcmccmr(i).read();
|
||||
ctx.csgcm[i] = T::regs().csgcmr(i).read();
|
||||
@ -1750,7 +1750,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
T::regs().init(1).ivlr().write_value(ctx.iv[2]);
|
||||
T::regs().init(1).ivrr().write_value(ctx.iv[3]);
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
for i in 0..8 {
|
||||
T::regs().csgcmccmr(i).write_value(ctx.csgcmccm[i]);
|
||||
T::regs().csgcmr(i).write_value(ctx.csgcm[i]);
|
||||
@ -1797,7 +1797,8 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
let num_words = blocks.len() / 4;
|
||||
let src_ptr = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
|
||||
let options = TransferOptions {
|
||||
priority: Priority::High,
|
||||
#[cfg(not(gpdma))]
|
||||
priority: crate::dma::Priority::High,
|
||||
..Default::default()
|
||||
};
|
||||
let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) };
|
||||
@ -1806,7 +1807,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
dma_transfer.await;
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
fn write_words_blocking(&self, block_size: usize, blocks: &[u32]) {
|
||||
assert_eq!((blocks.len() * 4) % block_size, 0);
|
||||
let mut byte_counter: usize = 0;
|
||||
@ -1820,7 +1821,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cryp_v2, cryp_v3))]
|
||||
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
|
||||
async fn write_words(dma: &mut PeripheralRef<'_, DmaIn>, block_size: usize, blocks: &[u32])
|
||||
where
|
||||
DmaIn: crate::cryp::DmaIn<T>,
|
||||
@ -1836,7 +1837,8 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
let num_words = blocks.len();
|
||||
let src_ptr = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
|
||||
let options = TransferOptions {
|
||||
priority: Priority::High,
|
||||
#[cfg(not(gpdma))]
|
||||
priority: crate::dma::Priority::High,
|
||||
..Default::default()
|
||||
};
|
||||
let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) };
|
||||
@ -1875,7 +1877,8 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> {
|
||||
let num_words = blocks.len() / 4;
|
||||
let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words);
|
||||
let options = TransferOptions {
|
||||
priority: Priority::VeryHigh,
|
||||
#[cfg(not(gpdma))]
|
||||
priority: crate::dma::Priority::VeryHigh,
|
||||
..Default::default()
|
||||
};
|
||||
let dma_transfer = unsafe { Transfer::new_read_raw(dma, dma_request, src_ptr, dst_ptr, options) };
|
||||
|
@ -4,6 +4,7 @@ use core::marker::PhantomData;
|
||||
use core::sync::atomic::{fence, Ordering};
|
||||
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
use stm32_metapac::syscfg::vals::EthSelPhy;
|
||||
|
||||
pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing};
|
||||
use super::*;
|
||||
@ -80,19 +81,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
phy: P,
|
||||
mac_addr: [u8; 6],
|
||||
) -> Self {
|
||||
// Enable the necessary Clocks
|
||||
#[cfg(not(rcc_h5))]
|
||||
critical_section::with(|_| {
|
||||
crate::pac::RCC.ahb1enr().modify(|w| {
|
||||
w.set_eth1macen(true);
|
||||
w.set_eth1txen(true);
|
||||
w.set_eth1rxen(true);
|
||||
});
|
||||
|
||||
crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b100));
|
||||
});
|
||||
|
||||
#[cfg(rcc_h5)]
|
||||
// Enable the necessary clocks
|
||||
critical_section::with(|_| {
|
||||
crate::pac::RCC.ahb1enr().modify(|w| {
|
||||
w.set_ethen(true);
|
||||
@ -100,9 +89,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
w.set_ethrxen(true);
|
||||
});
|
||||
|
||||
crate::pac::SYSCFG
|
||||
.pmcr()
|
||||
.modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4));
|
||||
crate::pac::SYSCFG.pmcr().modify(|w| w.set_eth_sel_phy(EthSelPhy::RMII));
|
||||
});
|
||||
|
||||
into_ref!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
|
||||
@ -145,19 +132,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
phy: P,
|
||||
mac_addr: [u8; 6],
|
||||
) -> Self {
|
||||
// Enable necessary clocks.
|
||||
#[cfg(not(rcc_h5))]
|
||||
critical_section::with(|_| {
|
||||
crate::pac::RCC.ahb1enr().modify(|w| {
|
||||
w.set_eth1macen(true);
|
||||
w.set_eth1txen(true);
|
||||
w.set_eth1rxen(true);
|
||||
});
|
||||
|
||||
crate::pac::SYSCFG.pmcr().modify(|w| w.set_epis(0b000));
|
||||
});
|
||||
|
||||
#[cfg(rcc_h5)]
|
||||
// Enable the necessary clocks
|
||||
critical_section::with(|_| {
|
||||
crate::pac::RCC.ahb1enr().modify(|w| {
|
||||
w.set_ethen(true);
|
||||
@ -165,10 +140,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
|
||||
w.set_ethrxen(true);
|
||||
});
|
||||
|
||||
// TODO: This is for RMII - what would MII need here?
|
||||
crate::pac::SYSCFG
|
||||
.pmcr()
|
||||
.modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4));
|
||||
.modify(|w| w.set_eth_sel_phy(EthSelPhy::MII_GMII));
|
||||
});
|
||||
|
||||
into_ref!(rx_clk, tx_clk, mdio, mdc, rxdv, rx_d0, rx_d1, rx_d2, rx_d3, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(async_fn_in_trait)]
|
||||
#![cfg_attr(
|
||||
docsrs,
|
||||
doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-stm32'>browse the `embassy-stm32` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (STM32H755 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n"
|
||||
doc = "<div style='padding:30px;background:#810;color:#fff;text-align:center;'><p>You might want to <a href='https://docs.embassy.dev/embassy-stm32'>browse the `embassy-stm32` documentation on the Embassy website</a> instead.</p><p>The documentation here on `docs.rs` is built for a single chip only (stm32h7, stm32h7rs55 in particular), while on the Embassy website you can pick your exact chip from the top menu. Available peripherals and their APIs change depending on the chip.</p></div>\n\n"
|
||||
)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
#![warn(missing_docs)]
|
||||
@ -303,9 +303,9 @@ pub fn init(config: Config) -> Peripherals {
|
||||
|
||||
#[cfg(not(any(stm32f1, stm32wb, stm32wl)))]
|
||||
peripherals::SYSCFG::enable_and_reset_with_cs(cs);
|
||||
#[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))]
|
||||
#[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))]
|
||||
peripherals::PWR::enable_and_reset_with_cs(cs);
|
||||
#[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))]
|
||||
#[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs)))]
|
||||
peripherals::FLASH::enable_and_reset_with_cs(cs);
|
||||
|
||||
// Enable the VDDIO2 power supply on chips that have it.
|
||||
|
@ -198,7 +198,7 @@ impl LsConfig {
|
||||
}
|
||||
|
||||
// If not OK, reset backup domain and configure it.
|
||||
#[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32c0)))]
|
||||
#[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32h7rs, stm32c0)))]
|
||||
{
|
||||
bdcr().modify(|w| w.set_bdrst(true));
|
||||
bdcr().modify(|w| w.set_bdrst(false));
|
||||
@ -210,11 +210,12 @@ impl LsConfig {
|
||||
// letting half our RAM go magically *poof*.
|
||||
// STM32H503CB/EB/KB/RB device errata - 2.2.8 SRAM2 unduly erased upon a backup domain reset
|
||||
// STM32H562xx/563xx/573xx device errata - 2.2.14 SRAM2 is erased when the backup domain is reset
|
||||
//#[cfg(any(stm32h5))]
|
||||
//{
|
||||
// bdcr().modify(|w| w.set_vswrst(true));
|
||||
// bdcr().modify(|w| w.set_vswrst(false));
|
||||
//}
|
||||
//#[cfg(any(stm32h5, stm32h7rs))]
|
||||
#[cfg(any(stm32h7rs))]
|
||||
{
|
||||
bdcr().modify(|w| w.set_vswrst(true));
|
||||
bdcr().modify(|w| w.set_vswrst(false));
|
||||
}
|
||||
#[cfg(any(stm32c0, stm32l0))]
|
||||
{
|
||||
bdcr().modify(|w| w.set_rtcrst(true));
|
||||
|
@ -1,7 +1,6 @@
|
||||
use core::ops::RangeInclusive;
|
||||
|
||||
use crate::pac;
|
||||
use crate::pac::pwr::vals::Vos;
|
||||
pub use crate::pac::rcc::vals::{
|
||||
Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
|
||||
};
|
||||
@ -22,9 +21,12 @@ const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(128_000_000)..=Hertz(560_000
|
||||
const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(836_000_000);
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
|
||||
const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(960_000_000);
|
||||
#[cfg(any(stm32h7rs))]
|
||||
const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(384_000_000)..=Hertz(1672_000_000);
|
||||
|
||||
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
|
||||
|
||||
#[cfg(any(stm32h5, stm32h7))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum VoltageScale {
|
||||
Scale0,
|
||||
@ -32,6 +34,8 @@ pub enum VoltageScale {
|
||||
Scale2,
|
||||
Scale3,
|
||||
}
|
||||
#[cfg(any(stm32h7rs))]
|
||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum HseMode {
|
||||
@ -40,7 +44,7 @@ pub enum HseMode {
|
||||
/// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
|
||||
Bypass,
|
||||
/// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
|
||||
#[cfg(any(rcc_h5, rcc_h50))]
|
||||
#[cfg(any(rcc_h5, rcc_h50, rcc_h7rs))]
|
||||
BypassDigital,
|
||||
}
|
||||
|
||||
@ -65,8 +69,8 @@ pub struct Pll {
|
||||
|
||||
/// PLL P division factor. If None, PLL P output is disabled.
|
||||
/// On PLL1, it must be even for most series (in particular,
|
||||
/// it cannot be 1 in series other than STM32H723/733,
|
||||
/// STM32H725/735 and STM32H730.)
|
||||
/// it cannot be 1 in series other than stm32h7, stm32h7rs23/733,
|
||||
/// stm32h7, stm32h7rs25/735 and stm32h7, stm32h7rs30.)
|
||||
pub divp: Option<PllDiv>,
|
||||
/// PLL Q division factor. If None, PLL Q output is disabled.
|
||||
pub divq: Option<PllDiv>,
|
||||
@ -115,7 +119,7 @@ impl From<TimerPrescaler> for Timpre {
|
||||
|
||||
/// Power supply configuration
|
||||
/// See RM0433 Rev 4 7.4
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
#[derive(PartialEq)]
|
||||
pub enum SupplyConfig {
|
||||
/// Default power supply configuration.
|
||||
@ -164,8 +168,15 @@ pub enum SupplyConfig {
|
||||
/// SMPS step-down converter voltage output level.
|
||||
/// This is only used in certain power supply configurations:
|
||||
/// SMPSLDO, SMPSExternalLDO, SMPSExternalLDOBypass.
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
pub use pac::pwr::vals::Sdlevel as SMPSSupplyVoltage;
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
pub enum SMPSSupplyVoltage {
|
||||
/// 1.8v
|
||||
V1_8,
|
||||
/// 2.5v
|
||||
#[cfg(not(pwr_h7rs))]
|
||||
V2_5,
|
||||
}
|
||||
|
||||
/// Configuration of the core clocks
|
||||
#[non_exhaustive]
|
||||
@ -178,22 +189,26 @@ pub struct Config {
|
||||
|
||||
pub pll1: Option<Pll>,
|
||||
pub pll2: Option<Pll>,
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
pub pll3: Option<Pll>,
|
||||
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
pub d1c_pre: AHBPrescaler,
|
||||
pub ahb_pre: AHBPrescaler,
|
||||
pub apb1_pre: APBPrescaler,
|
||||
pub apb2_pre: APBPrescaler,
|
||||
#[cfg(not(stm32h7rs))]
|
||||
pub apb3_pre: APBPrescaler,
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
pub apb4_pre: APBPrescaler,
|
||||
#[cfg(stm32h7rs)]
|
||||
pub apb5_pre: APBPrescaler,
|
||||
|
||||
pub timer_prescaler: TimerPrescaler,
|
||||
pub voltage_scale: VoltageScale,
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
pub supply_config: SupplyConfig,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
@ -210,23 +225,30 @@ impl Default for Config {
|
||||
sys: Sysclk::HSI,
|
||||
pll1: None,
|
||||
pll2: None,
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
pll3: None,
|
||||
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
d1c_pre: AHBPrescaler::DIV1,
|
||||
ahb_pre: AHBPrescaler::DIV1,
|
||||
apb1_pre: APBPrescaler::DIV1,
|
||||
apb2_pre: APBPrescaler::DIV1,
|
||||
#[cfg(not(stm32h7rs))]
|
||||
apb3_pre: APBPrescaler::DIV1,
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
apb4_pre: APBPrescaler::DIV1,
|
||||
#[cfg(stm32h7rs)]
|
||||
apb5_pre: APBPrescaler::DIV1,
|
||||
|
||||
timer_prescaler: TimerPrescaler::DefaultX2,
|
||||
#[cfg(not(rcc_h7rs))]
|
||||
voltage_scale: VoltageScale::Scale0,
|
||||
#[cfg(rcc_h7rs)]
|
||||
voltage_scale: VoltageScale::HIGH,
|
||||
ls: Default::default(),
|
||||
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
supply_config: SupplyConfig::Default,
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
supply_config: SupplyConfig::LDO,
|
||||
|
||||
mux: Default::default(),
|
||||
}
|
||||
@ -234,24 +256,30 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init(config: Config) {
|
||||
#[cfg(any(stm32h7))]
|
||||
let pwr_reg = PWR.cr3();
|
||||
#[cfg(any(stm32h7rs))]
|
||||
let pwr_reg = PWR.csr2();
|
||||
|
||||
// NB. The lower bytes of CR3 can only be written once after
|
||||
// POR, and must be written with a valid combination. Refer to
|
||||
// RM0433 Rev 7 6.8.4. This is partially enforced by dropping
|
||||
// `self` at the end of this method, but of course we cannot
|
||||
// know what happened between the previous POR and here.
|
||||
#[cfg(pwr_h7rm0433)]
|
||||
PWR.cr3().modify(|w| {
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_scuen(true);
|
||||
w.set_ldoen(true);
|
||||
w.set_bypass(false);
|
||||
});
|
||||
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
{
|
||||
use pac::pwr::vals::Sdlevel;
|
||||
match config.supply_config {
|
||||
SupplyConfig::Default => {
|
||||
PWR.cr3().modify(|w| {
|
||||
w.set_sdlevel(SMPSSupplyVoltage::RESET);
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_sdlevel(Sdlevel::RESET);
|
||||
w.set_sdexthp(false);
|
||||
w.set_sden(true);
|
||||
w.set_ldoen(true);
|
||||
@ -259,25 +287,30 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
});
|
||||
}
|
||||
SupplyConfig::LDO => {
|
||||
PWR.cr3().modify(|w| {
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_sden(false);
|
||||
w.set_ldoen(true);
|
||||
w.set_bypass(false);
|
||||
});
|
||||
}
|
||||
SupplyConfig::DirectSMPS => {
|
||||
PWR.cr3().modify(|w| {
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_sdexthp(false);
|
||||
w.set_sden(true);
|
||||
w.set_ldoen(false);
|
||||
w.set_bypass(false);
|
||||
});
|
||||
}
|
||||
SupplyConfig::SMPSLDO(smps_supply_voltage)
|
||||
| SupplyConfig::SMPSExternalLDO(smps_supply_voltage)
|
||||
| SupplyConfig::SMPSExternalLDOBypass(smps_supply_voltage) => {
|
||||
PWR.cr3().modify(|w| {
|
||||
w.set_sdlevel(smps_supply_voltage);
|
||||
SupplyConfig::SMPSLDO(sdlevel)
|
||||
| SupplyConfig::SMPSExternalLDO(sdlevel)
|
||||
| SupplyConfig::SMPSExternalLDOBypass(sdlevel) => {
|
||||
let sdlevel = match sdlevel {
|
||||
SMPSSupplyVoltage::V1_8 => Sdlevel::V1_8,
|
||||
#[cfg(not(pwr_h7rs))]
|
||||
SMPSSupplyVoltage::V2_5 => Sdlevel::V2_5,
|
||||
};
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_sdlevel(sdlevel);
|
||||
w.set_sdexthp(matches!(
|
||||
config.supply_config,
|
||||
SupplyConfig::SMPSExternalLDO(_) | SupplyConfig::SMPSExternalLDOBypass(_)
|
||||
@ -291,7 +324,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
});
|
||||
}
|
||||
SupplyConfig::SMPSDisabledLDOBypass => {
|
||||
PWR.cr3().modify(|w| {
|
||||
pwr_reg.modify(|w| {
|
||||
w.set_sden(false);
|
||||
w.set_ldoen(false);
|
||||
w.set_bypass(true);
|
||||
@ -305,43 +338,49 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
// in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
|
||||
// VOS = Scale 3, so check that the voltage on the VCAP pins =
|
||||
// 1.0V.
|
||||
#[cfg(any(pwr_h7rm0433, pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
#[cfg(any(stm32h7))]
|
||||
while !PWR.csr1().read().actvosrdy() {}
|
||||
#[cfg(any(stm32h7rs))]
|
||||
while !PWR.sr1().read().actvosrdy() {}
|
||||
|
||||
// Configure voltage scale.
|
||||
#[cfg(any(pwr_h5, pwr_h50))]
|
||||
{
|
||||
PWR.voscr().modify(|w| {
|
||||
w.set_vos(match config.voltage_scale {
|
||||
VoltageScale::Scale0 => Vos::SCALE0,
|
||||
VoltageScale::Scale1 => Vos::SCALE1,
|
||||
VoltageScale::Scale2 => Vos::SCALE2,
|
||||
VoltageScale::Scale3 => Vos::SCALE3,
|
||||
VoltageScale::Scale0 => crate::pac::pwr::vals::Vos::SCALE0,
|
||||
VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
|
||||
VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
|
||||
VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
|
||||
})
|
||||
});
|
||||
while !PWR.vossr().read().vosrdy() {}
|
||||
}
|
||||
|
||||
#[cfg(syscfg_h7)]
|
||||
{
|
||||
// in chips without the overdrive bit, we can go from any scale to any scale directly.
|
||||
PWR.d3cr().modify(|w| {
|
||||
w.set_vos(match config.voltage_scale {
|
||||
VoltageScale::Scale0 => Vos::SCALE0,
|
||||
VoltageScale::Scale1 => Vos::SCALE1,
|
||||
VoltageScale::Scale2 => Vos::SCALE2,
|
||||
VoltageScale::Scale3 => Vos::SCALE3,
|
||||
VoltageScale::Scale0 => crate::pac::pwr::vals::Vos::SCALE0,
|
||||
VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
|
||||
VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
|
||||
VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
|
||||
})
|
||||
});
|
||||
while !PWR.d3cr().read().vosrdy() {}
|
||||
}
|
||||
#[cfg(pwr_h7rs)]
|
||||
{
|
||||
PWR.csr4().modify(|w| w.set_vos(config.voltage_scale));
|
||||
while !PWR.csr4().read().vosrdy() {}
|
||||
}
|
||||
|
||||
#[cfg(syscfg_h7od)]
|
||||
{
|
||||
match config.voltage_scale {
|
||||
VoltageScale::Scale0 => {
|
||||
// to go to scale0, we must go to Scale1 first...
|
||||
PWR.d3cr().modify(|w| w.set_vos(Vos::SCALE1));
|
||||
PWR.d3cr().modify(|w| w.set_vos(crate::pac::pwr::vals::Vos::SCALE1));
|
||||
while !PWR.d3cr().read().vosrdy() {}
|
||||
|
||||
// Then enable overdrive.
|
||||
@ -353,9 +392,9 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
PWR.d3cr().modify(|w| {
|
||||
w.set_vos(match config.voltage_scale {
|
||||
VoltageScale::Scale0 => unreachable!(),
|
||||
VoltageScale::Scale1 => Vos::SCALE1,
|
||||
VoltageScale::Scale2 => Vos::SCALE2,
|
||||
VoltageScale::Scale3 => Vos::SCALE3,
|
||||
VoltageScale::Scale1 => crate::pac::pwr::vals::Vos::SCALE1,
|
||||
VoltageScale::Scale2 => crate::pac::pwr::vals::Vos::SCALE2,
|
||||
VoltageScale::Scale3 => crate::pac::pwr::vals::Vos::SCALE3,
|
||||
})
|
||||
});
|
||||
while !PWR.d3cr().read().vosrdy() {}
|
||||
@ -388,7 +427,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
Some(hse) => {
|
||||
RCC.cr().modify(|w| {
|
||||
w.set_hsebyp(hse.mode != HseMode::Oscillator);
|
||||
#[cfg(any(rcc_h5, rcc_h50))]
|
||||
#[cfg(any(rcc_h5, rcc_h50, rcc_h7rs))]
|
||||
w.set_hseext(match hse.mode {
|
||||
HseMode::Oscillator | HseMode::Bypass => pac::rcc::vals::Hseext::ANALOG,
|
||||
HseMode::BypassDigital => pac::rcc::vals::Hseext::DIGITAL,
|
||||
@ -414,7 +453,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
};
|
||||
|
||||
// H7 has shared PLLSRC, check it's equal in all PLLs.
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
{
|
||||
let plls = [&config.pll1, &config.pll2, &config.pll3];
|
||||
if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
|
||||
@ -426,7 +465,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
let pll_input = PllInput { csi, hse, hsi };
|
||||
let pll1 = init_pll(0, config.pll1, &pll_input);
|
||||
let pll2 = init_pll(1, config.pll2, &pll_input);
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
let pll3 = init_pll(2, config.pll3, &pll_input);
|
||||
|
||||
// Configure sysclk
|
||||
@ -474,8 +513,13 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
VoltageScale::Scale2 => (Hertz(300_000_000), Hertz(150_000_000), Hertz(75_000_000)),
|
||||
VoltageScale::Scale3 => (Hertz(200_000_000), Hertz(100_000_000), Hertz(50_000_000)),
|
||||
};
|
||||
#[cfg(stm32h7rs)]
|
||||
let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
|
||||
VoltageScale::HIGH => (Hertz(600_000_000), Hertz(300_000_000), Hertz(150_000_000)),
|
||||
VoltageScale::LOW => (Hertz(400_000_000), Hertz(200_000_000), Hertz(100_000_000)),
|
||||
};
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
let hclk = {
|
||||
let d1cpre_clk = sys / config.d1c_pre;
|
||||
assert!(d1cpre_clk <= d1cpre_clk_max);
|
||||
@ -491,12 +535,18 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
let apb2 = hclk / config.apb2_pre;
|
||||
let apb2_tim = apb_div_tim(&config.apb2_pre, hclk, config.timer_prescaler);
|
||||
assert!(apb2 <= pclk_max);
|
||||
#[cfg(not(stm32h7rs))]
|
||||
let apb3 = hclk / config.apb3_pre;
|
||||
#[cfg(not(stm32h7rs))]
|
||||
assert!(apb3 <= pclk_max);
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
let apb4 = hclk / config.apb4_pre;
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
assert!(apb4 <= pclk_max);
|
||||
#[cfg(stm32h7rs)]
|
||||
let apb5 = hclk / config.apb5_pre;
|
||||
#[cfg(stm32h7rs)]
|
||||
assert!(apb5 <= pclk_max);
|
||||
|
||||
flash_setup(hclk, config.voltage_scale);
|
||||
|
||||
@ -520,6 +570,25 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
w.set_d3ppre(config.apb4_pre);
|
||||
});
|
||||
}
|
||||
#[cfg(stm32h7rs)]
|
||||
{
|
||||
RCC.cdcfgr().write(|w| {
|
||||
w.set_cpre(config.d1c_pre);
|
||||
});
|
||||
while RCC.cdcfgr().read().cpre() != config.d1c_pre {}
|
||||
|
||||
RCC.bmcfgr().write(|w| {
|
||||
w.set_bmpre(config.ahb_pre);
|
||||
});
|
||||
while RCC.bmcfgr().read().bmpre() != config.ahb_pre {}
|
||||
|
||||
RCC.apbcfgr().modify(|w| {
|
||||
w.set_ppre1(config.apb1_pre);
|
||||
w.set_ppre2(config.apb2_pre);
|
||||
w.set_ppre4(config.apb4_pre);
|
||||
w.set_ppre5(config.apb5_pre);
|
||||
});
|
||||
}
|
||||
#[cfg(stm32h5)]
|
||||
{
|
||||
// Set hpre
|
||||
@ -540,7 +609,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
while RCC.cfgr().read().sws() != config.sys {}
|
||||
|
||||
// IO compensation cell - Requires CSI clock and SYSCFG
|
||||
#[cfg(stm32h7)] // TODO h5
|
||||
#[cfg(any(stm32h7))] // TODO h5, h7rs
|
||||
if csi.is_some() {
|
||||
// Enable the compensation cell, using back-bias voltage code
|
||||
// provide by the cell.
|
||||
@ -551,7 +620,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
w.set_hslv(false);
|
||||
})
|
||||
});
|
||||
while !pac::SYSCFG.cccsr().read().ready() {}
|
||||
while !pac::SYSCFG.cccsr().read().rdy() {}
|
||||
}
|
||||
|
||||
config.mux.init();
|
||||
@ -562,11 +631,17 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
hclk2: Some(hclk),
|
||||
hclk3: Some(hclk),
|
||||
hclk4: Some(hclk),
|
||||
#[cfg(stm32h7rs)]
|
||||
hclk5: Some(hclk),
|
||||
pclk1: Some(apb1),
|
||||
pclk2: Some(apb2),
|
||||
#[cfg(not(stm32h7rs))]
|
||||
pclk3: Some(apb3),
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
pclk4: Some(apb4),
|
||||
#[cfg(stm32h7rs)]
|
||||
pclk5: Some(apb5),
|
||||
|
||||
pclk1_tim: Some(apb1_tim),
|
||||
pclk2_tim: Some(apb2_tim),
|
||||
rtc: rtc,
|
||||
@ -584,11 +659,15 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
pll2_p: pll2.p,
|
||||
pll2_q: pll2.q,
|
||||
pll2_r: pll2.r,
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(stm32h7rs)]
|
||||
pll2_s: None, // TODO
|
||||
#[cfg(stm32h7rs)]
|
||||
pll2_t: None, // TODO
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
pll3_p: pll3.p,
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
pll3_q: pll3.q,
|
||||
#[cfg(any(rcc_h5, stm32h7))]
|
||||
#[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
|
||||
pll3_r: pll3.r,
|
||||
|
||||
#[cfg(rcc_h50)]
|
||||
@ -601,8 +680,14 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
#[cfg(stm32h5)]
|
||||
audioclk: None,
|
||||
i2s_ckin: None,
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
dsi_phy: None, // TODO
|
||||
#[cfg(stm32h7rs)]
|
||||
spdifrx_symb: None, // TODO
|
||||
#[cfg(stm32h7rs)]
|
||||
clk48mohci: None, // TODO
|
||||
#[cfg(stm32h7rs)]
|
||||
usb: None, // TODO
|
||||
);
|
||||
}
|
||||
|
||||
@ -627,7 +712,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
|
||||
while RCC.cr().read().pllrdy(num) {}
|
||||
|
||||
// "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0)));
|
||||
#[cfg(stm32h5)]
|
||||
RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));
|
||||
@ -696,7 +781,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
|
||||
w.set_pllren(r.is_some());
|
||||
});
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
#[cfg(any(stm32h7, stm32h7rs))]
|
||||
{
|
||||
RCC.pllckselr().modify(|w| {
|
||||
w.set_divm(num, config.prediv);
|
||||
@ -850,6 +935,26 @@ fn flash_setup(clk: Hertz, vos: VoltageScale) {
|
||||
(VoltageScale::Scale3, ..=88) => (3, 1),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
#[cfg(flash_h7rs)]
|
||||
let (latency, wrhighfreq) = match (vos, clk.0) {
|
||||
// VOS high range VCORE 1.30V - 1.40V
|
||||
(VoltageScale::HIGH, ..=40_000_000) => (0, 0),
|
||||
(VoltageScale::HIGH, ..=80_000_000) => (1, 0),
|
||||
(VoltageScale::HIGH, ..=120_000_000) => (2, 1),
|
||||
(VoltageScale::HIGH, ..=160_000_000) => (3, 1),
|
||||
(VoltageScale::HIGH, ..=200_000_000) => (4, 2),
|
||||
(VoltageScale::HIGH, ..=240_000_000) => (5, 2),
|
||||
(VoltageScale::HIGH, ..=280_000_000) => (6, 3),
|
||||
(VoltageScale::HIGH, ..=320_000_000) => (7, 3),
|
||||
// VOS low range VCORE 1.15V - 1.26V
|
||||
(VoltageScale::LOW, ..=36_000_000) => (0, 0),
|
||||
(VoltageScale::LOW, ..=72_000_000) => (1, 0),
|
||||
(VoltageScale::LOW, ..=108_000_000) => (2, 1),
|
||||
(VoltageScale::LOW, ..=144_000_000) => (3, 1),
|
||||
(VoltageScale::LOW, ..=180_000_000) => (4, 2),
|
||||
(VoltageScale::LOW, ..=216_000_000) => (5, 2),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
|
||||
|
||||
|
@ -33,9 +33,9 @@ pub(crate) fn init_hsi48(config: Hsi48Config) -> Hertz {
|
||||
});
|
||||
|
||||
// Enable HSI48
|
||||
#[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32u5, stm32wba, stm32f0)))]
|
||||
#[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0)))]
|
||||
let r = RCC.crrcr();
|
||||
#[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32u5, stm32wba))]
|
||||
#[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba))]
|
||||
let r = RCC.cr();
|
||||
#[cfg(any(stm32f0))]
|
||||
let r = RCC.cr2();
|
||||
|
@ -5,9 +5,31 @@ use embassy_hal_internal::into_ref;
|
||||
use crate::gpio::{AFType, Speed};
|
||||
#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))]
|
||||
pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
|
||||
#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
|
||||
#[cfg(not(any(
|
||||
rcc_f2,
|
||||
rcc_f410,
|
||||
rcc_f4,
|
||||
rcc_f7,
|
||||
rcc_h50,
|
||||
rcc_h5,
|
||||
rcc_h7ab,
|
||||
rcc_h7rm0433,
|
||||
rcc_h7,
|
||||
rcc_h7rs
|
||||
)))]
|
||||
pub use crate::pac::rcc::vals::Mcosel as McoSource;
|
||||
#[cfg(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7))]
|
||||
#[cfg(any(
|
||||
rcc_f2,
|
||||
rcc_f410,
|
||||
rcc_f4,
|
||||
rcc_f7,
|
||||
rcc_h50,
|
||||
rcc_h5,
|
||||
rcc_h7ab,
|
||||
rcc_h7rm0433,
|
||||
rcc_h7,
|
||||
rcc_h7rs
|
||||
))]
|
||||
pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
|
||||
use crate::pac::RCC;
|
||||
use crate::{peripherals, Peripheral};
|
||||
|
@ -24,7 +24,7 @@ pub use hsi48::*;
|
||||
#[cfg_attr(stm32c0, path = "c0.rs")]
|
||||
#[cfg_attr(stm32g0, path = "g0.rs")]
|
||||
#[cfg_attr(stm32g4, path = "g4.rs")]
|
||||
#[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")]
|
||||
#[cfg_attr(any(stm32h5, stm32h7, stm32h7rs), path = "h.rs")]
|
||||
#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")]
|
||||
#[cfg_attr(stm32u5, path = "u5.rs")]
|
||||
#[cfg_attr(stm32wba, path = "wba.rs")]
|
||||
|
@ -58,7 +58,7 @@ pub(crate) fn init(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(stm32h5, stm32u5))]
|
||||
#[cfg(any(stm32h5, stm32u5, stm32h7rs))]
|
||||
{
|
||||
crate::pac::PWR.ucpdr().modify(|w| {
|
||||
w.set_ucpd_dbdis(!ucpd1_db_enable);
|
||||
|
@ -371,7 +371,7 @@ foreach_interrupt!(
|
||||
} else if #[cfg(stm32g0x1)] {
|
||||
const FIFO_DEPTH_WORDS: u16 = 512;
|
||||
const ENDPOINT_COUNT: usize = 8;
|
||||
} else if #[cfg(stm32h7)] {
|
||||
} else if #[cfg(any(stm32h7, stm32h7rs))] {
|
||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||
const ENDPOINT_COUNT: usize = 9;
|
||||
} else if #[cfg(stm32u5)] {
|
||||
@ -420,7 +420,7 @@ foreach_interrupt!(
|
||||
stm32f469,
|
||||
stm32f479,
|
||||
stm32f7,
|
||||
stm32h7,
|
||||
stm32h7, stm32h7rs,
|
||||
))] {
|
||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||
const ENDPOINT_COUNT: usize = 9;
|
||||
|
8
examples/stm32h7rs/.cargo/config.toml
Normal file
8
examples/stm32h7rs/.cargo/config.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[target.thumbv7em-none-eabihf]
|
||||
runner = 'probe-rs run --chip STM32H7S3L8Hx'
|
||||
|
||||
[build]
|
||||
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "trace"
|
73
examples/stm32h7rs/Cargo.toml
Normal file
73
examples/stm32h7rs/Cargo.toml
Normal file
@ -0,0 +1,73 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "embassy-stm32h7-examples"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
# Change stm32h743bi to your chip name, if necessary.
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
|
||||
embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||
embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
|
||||
embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||
embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
|
||||
embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||
|
||||
defmt = "0.3"
|
||||
defmt-rtt = "0.4"
|
||||
|
||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
|
||||
embedded-hal-async = { version = "1.0" }
|
||||
embedded-nal-async = { version = "0.7.1" }
|
||||
embedded-io-async = { version = "0.6.1" }
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
heapless = { version = "0.8", default-features = false }
|
||||
rand_core = "0.6.3"
|
||||
critical-section = "1.1"
|
||||
micromath = "2.0.0"
|
||||
stm32-fmc = "0.3.0"
|
||||
embedded-storage = "0.3.1"
|
||||
static_cell = "2"
|
||||
chrono = { version = "^0.4", default-features = false }
|
||||
|
||||
# cargo build/run
|
||||
[profile.dev]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
debug-assertions = true # <-
|
||||
incremental = false
|
||||
opt-level = 3 # <-
|
||||
overflow-checks = true # <-
|
||||
|
||||
# cargo test
|
||||
[profile.test]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
debug-assertions = true # <-
|
||||
incremental = false
|
||||
opt-level = 3 # <-
|
||||
overflow-checks = true # <-
|
||||
|
||||
# cargo build/run --release
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
debug-assertions = false # <-
|
||||
incremental = false
|
||||
lto = 'fat'
|
||||
opt-level = 3 # <-
|
||||
overflow-checks = false # <-
|
||||
|
||||
# cargo test --release
|
||||
[profile.bench]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
debug-assertions = false # <-
|
||||
incremental = false
|
||||
lto = 'fat'
|
||||
opt-level = 3 # <-
|
||||
overflow-checks = false # <-
|
5
examples/stm32h7rs/build.rs
Normal file
5
examples/stm32h7rs/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");
|
||||
}
|
51
examples/stm32h7rs/src/bin/blinky.rs
Normal file
51
examples/stm32h7rs/src/bin/blinky.rs
Normal file
@ -0,0 +1,51 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::Config;
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(24_000_000),
|
||||
mode: HseMode::Oscillator,
|
||||
});
|
||||
config.rcc.pll1 = Some(Pll {
|
||||
source: PllSource::HSE,
|
||||
prediv: PllPreDiv::DIV3,
|
||||
mul: PllMul::MUL150,
|
||||
divp: Some(PllDiv::DIV2),
|
||||
divq: None,
|
||||
divr: None,
|
||||
});
|
||||
config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
|
||||
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz
|
||||
config.rcc.apb1_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb2_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb5_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.voltage_scale = VoltageScale::HIGH;
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
let mut led = Output::new(p.PD10, Level::High, Speed::Low);
|
||||
|
||||
loop {
|
||||
info!("high");
|
||||
led.set_high();
|
||||
Timer::after_millis(500).await;
|
||||
|
||||
info!("low");
|
||||
led.set_low();
|
||||
Timer::after_millis(500).await;
|
||||
}
|
||||
}
|
25
examples/stm32h7rs/src/bin/button_exti.rs
Normal file
25
examples/stm32h7rs/src/bin/button_exti.rs
Normal file
@ -0,0 +1,25 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::exti::ExtiInput;
|
||||
use embassy_stm32::gpio::Pull;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up);
|
||||
|
||||
info!("Press the USER button...");
|
||||
|
||||
loop {
|
||||
button.wait_for_falling_edge().await;
|
||||
info!("Pressed!");
|
||||
button.wait_for_rising_edge().await;
|
||||
info!("Released!");
|
||||
}
|
||||
}
|
98
examples/stm32h7rs/src/bin/can.rs
Normal file
98
examples/stm32h7rs/src/bin/can.rs
Normal file
@ -0,0 +1,98 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::{bind_interrupts, can, rcc, Config};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
|
||||
FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
config.rcc.hse = Some(rcc::Hse {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
mode: rcc::HseMode::Oscillator,
|
||||
});
|
||||
config.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
|
||||
//let mut can = can.into_internal_loopback_mode();
|
||||
let mut can = can.into_normal_mode();
|
||||
|
||||
info!("CAN Configured");
|
||||
|
||||
let mut i = 0;
|
||||
let mut last_read_ts = embassy_time::Instant::now();
|
||||
|
||||
loop {
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
"Rx: {:x} {:x} {:x} {:x} --- NEW {}",
|
||||
rx_frame.data()[0],
|
||||
rx_frame.data()[1],
|
||||
rx_frame.data()[2],
|
||||
rx_frame.data()[3],
|
||||
delta,
|
||||
)
|
||||
}
|
||||
Err(_err) => error!("Error in frame"),
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
i += 1;
|
||||
if i > 3 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let (mut tx, mut rx, _props) = can.split();
|
||||
// With split
|
||||
loop {
|
||||
let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap();
|
||||
info!("Writing frame");
|
||||
_ = tx.write(&frame).await;
|
||||
|
||||
match rx.read().await {
|
||||
Ok(envelope) => {
|
||||
let (rx_frame, ts) = envelope.parts();
|
||||
let delta = (ts - last_read_ts).as_millis();
|
||||
last_read_ts = ts;
|
||||
info!(
|
||||
"Rx: {:x} {:x} {:x} {:x} --- NEW {}",
|
||||
rx_frame.data()[0],
|
||||
rx_frame.data()[1],
|
||||
rx_frame.data()[2],
|
||||
rx_frame.data()[3],
|
||||
delta,
|
||||
)
|
||||
}
|
||||
Err(_err) => error!("Error in frame"),
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
i = i.wrapping_add(1);
|
||||
}
|
||||
}
|
29
examples/stm32h7rs/src/bin/mco.rs
Normal file
29
examples/stm32h7rs/src/bin/mco.rs
Normal file
@ -0,0 +1,29 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
||||
|
||||
let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8);
|
||||
|
||||
loop {
|
||||
info!("high");
|
||||
led.set_high();
|
||||
Timer::after_millis(500).await;
|
||||
|
||||
info!("low");
|
||||
led.set_low();
|
||||
Timer::after_millis(500).await;
|
||||
}
|
||||
}
|
150
examples/stm32h7rs/src/bin/multiprio.rs
Normal file
150
examples/stm32h7rs/src/bin/multiprio.rs
Normal file
@ -0,0 +1,150 @@
|
||||
//! This example showcases how to create multiple Executor instances to run tasks at
|
||||
//! different priority levels.
|
||||
//!
|
||||
//! Low priority executor runs in thread mode (not interrupt), and uses `sev` for signaling
|
||||
//! there's work in the queue, and `wfe` for waiting for work.
|
||||
//!
|
||||
//! Medium and high priority executors run in two interrupts with different priorities.
|
||||
//! Signaling work is done by pending the interrupt. No "waiting" needs to be done explicitly, since
|
||||
//! when there's work the interrupt will trigger and run the executor.
|
||||
//!
|
||||
//! Sample output below. Note that high priority ticks can interrupt everything else, and
|
||||
//! medium priority computations can interrupt low priority computations, making them to appear
|
||||
//! to take significantly longer time.
|
||||
//!
|
||||
//! ```not_rust
|
||||
//! [med] Starting long computation
|
||||
//! [med] done in 992 ms
|
||||
//! [high] tick!
|
||||
//! [low] Starting long computation
|
||||
//! [med] Starting long computation
|
||||
//! [high] tick!
|
||||
//! [high] tick!
|
||||
//! [med] done in 993 ms
|
||||
//! [med] Starting long computation
|
||||
//! [high] tick!
|
||||
//! [high] tick!
|
||||
//! [med] done in 993 ms
|
||||
//! [low] done in 3972 ms
|
||||
//! [med] Starting long computation
|
||||
//! [high] tick!
|
||||
//! [high] tick!
|
||||
//! [med] done in 993 ms
|
||||
//! ```
|
||||
//!
|
||||
//! For comparison, try changing the code so all 3 tasks get spawned on the low priority executor.
|
||||
//! You will get an output like the following. Note that no computation is ever interrupted.
|
||||
//!
|
||||
//! ```not_rust
|
||||
//! [high] tick!
|
||||
//! [med] Starting long computation
|
||||
//! [med] done in 496 ms
|
||||
//! [low] Starting long computation
|
||||
//! [low] done in 992 ms
|
||||
//! [med] Starting long computation
|
||||
//! [med] done in 496 ms
|
||||
//! [high] tick!
|
||||
//! [low] Starting long computation
|
||||
//! [low] done in 992 ms
|
||||
//! [high] tick!
|
||||
//! [med] Starting long computation
|
||||
//! [med] done in 496 ms
|
||||
//! [high] tick!
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::{Executor, InterruptExecutor};
|
||||
use embassy_stm32::interrupt;
|
||||
use embassy_stm32::interrupt::{InterruptExt, Priority};
|
||||
use embassy_time::{Instant, Timer};
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run_high() {
|
||||
loop {
|
||||
info!(" [high] tick!");
|
||||
Timer::after_ticks(27374).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run_med() {
|
||||
loop {
|
||||
let start = Instant::now();
|
||||
info!(" [med] Starting long computation");
|
||||
|
||||
// Spin-wait to simulate a long CPU computation
|
||||
cortex_m::asm::delay(128_000_000); // ~1 second
|
||||
|
||||
let end = Instant::now();
|
||||
let ms = end.duration_since(start).as_ticks() / 33;
|
||||
info!(" [med] done in {} ms", ms);
|
||||
|
||||
Timer::after_ticks(23421).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run_low() {
|
||||
loop {
|
||||
let start = Instant::now();
|
||||
info!("[low] Starting long computation");
|
||||
|
||||
// Spin-wait to simulate a long CPU computation
|
||||
cortex_m::asm::delay(256_000_000); // ~2 seconds
|
||||
|
||||
let end = Instant::now();
|
||||
let ms = end.duration_since(start).as_ticks() / 33;
|
||||
info!("[low] done in {} ms", ms);
|
||||
|
||||
Timer::after_ticks(32983).await;
|
||||
}
|
||||
}
|
||||
|
||||
static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new();
|
||||
static EXECUTOR_MED: InterruptExecutor = InterruptExecutor::new();
|
||||
static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
#[interrupt]
|
||||
unsafe fn UART4() {
|
||||
EXECUTOR_HIGH.on_interrupt()
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
unsafe fn UART5() {
|
||||
EXECUTOR_MED.on_interrupt()
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
|
||||
let _p = embassy_stm32::init(Default::default());
|
||||
|
||||
// STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as
|
||||
// by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application.
|
||||
// In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt
|
||||
// vector would work exactly the same.
|
||||
|
||||
// High-priority executor: UART4, priority level 6
|
||||
interrupt::UART4.set_priority(Priority::P6);
|
||||
let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
|
||||
unwrap!(spawner.spawn(run_high()));
|
||||
|
||||
// Medium-priority executor: UART5, priority level 7
|
||||
interrupt::UART5.set_priority(Priority::P7);
|
||||
let spawner = EXECUTOR_MED.start(interrupt::UART5);
|
||||
unwrap!(spawner.spawn(run_med()));
|
||||
|
||||
// Low priority executor: runs in thread mode, using WFE/SEV
|
||||
let executor = EXECUTOR_LOW.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
unwrap!(spawner.spawn(run_low()));
|
||||
});
|
||||
}
|
26
examples/stm32h7rs/src/bin/rng.rs
Normal file
26
examples/stm32h7rs/src/bin/rng.rs
Normal file
@ -0,0 +1,26 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::rng::Rng;
|
||||
use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
config.rcc.hsi48 = Some(Default::default()); // needed for RNG
|
||||
let p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
let mut rng = Rng::new(p.RNG, Irqs);
|
||||
|
||||
let mut buf = [0u8; 16];
|
||||
unwrap!(rng.async_fill_bytes(&mut buf).await);
|
||||
info!("random bytes: {:02x}", buf);
|
||||
}
|
36
examples/stm32h7rs/src/bin/rtc.rs
Normal file
36
examples/stm32h7rs/src/bin/rtc.rs
Normal file
@ -0,0 +1,36 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::rcc::LsConfig;
|
||||
use embassy_stm32::rtc::{Rtc, RtcConfig};
|
||||
use embassy_stm32::Config;
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
config.rcc.ls = LsConfig::default_lse();
|
||||
|
||||
let p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
let now = NaiveDate::from_ymd_opt(2020, 5, 15)
|
||||
.unwrap()
|
||||
.and_hms_opt(10, 30, 15)
|
||||
.unwrap();
|
||||
|
||||
let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
|
||||
info!("Got RTC! {:?}", now.and_utc().timestamp());
|
||||
|
||||
rtc.set_datetime(now.into()).expect("datetime not set");
|
||||
|
||||
// In reality the delay would be much longer
|
||||
Timer::after_millis(20000).await;
|
||||
|
||||
let then: NaiveDateTime = rtc.now().unwrap().into();
|
||||
info!("Got RTC! {:?}", then.and_utc().timestamp());
|
||||
}
|
36
examples/stm32h7rs/src/bin/signal.rs
Normal file
36
examples/stm32h7rs/src/bin/signal.rs
Normal file
@ -0,0 +1,36 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::{info, unwrap};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::signal::Signal;
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new();
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn my_sending_task() {
|
||||
let mut counter: u32 = 0;
|
||||
|
||||
loop {
|
||||
Timer::after_secs(1).await;
|
||||
|
||||
SIGNAL.signal(counter);
|
||||
|
||||
counter = counter.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
let _p = embassy_stm32::init(Default::default());
|
||||
unwrap!(spawner.spawn(my_sending_task()));
|
||||
|
||||
loop {
|
||||
let received_counter = SIGNAL.wait().await;
|
||||
|
||||
info!("signalled, counter: {}", received_counter);
|
||||
}
|
||||
}
|
50
examples/stm32h7rs/src/bin/spi.rs
Normal file
50
examples/stm32h7rs/src/bin/spi.rs
Normal file
@ -0,0 +1,50 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
use core::str::from_utf8;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Blocking;
|
||||
use embassy_stm32::peripherals::SPI3;
|
||||
use embassy_stm32::spi;
|
||||
use embassy_stm32::time::mhz;
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, SPI3, Blocking>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
unsafe {
|
||||
let result = spi.blocking_transfer_in_place(write.as_bytes_mut());
|
||||
if let Err(_) = result {
|
||||
defmt::panic!("crap");
|
||||
}
|
||||
}
|
||||
info!("read via spi: {}", from_utf8(write.as_bytes()).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let mut spi_config = spi::Config::default();
|
||||
spi_config.frequency = mhz(1);
|
||||
|
||||
let spi = spi::Spi::new_blocking(p.SPI3, p.PB3, p.PB5, p.PB4, spi_config);
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
|
||||
executor.run(|spawner| {
|
||||
unwrap!(spawner.spawn(main_task(spi)));
|
||||
})
|
||||
}
|
46
examples/stm32h7rs/src/bin/spi_dma.rs
Normal file
46
examples/stm32h7rs/src/bin/spi_dma.rs
Normal file
@ -0,0 +1,46 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
use core::str::from_utf8;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{peripherals, spi};
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(mut spi: spi::Spi<'static, peripherals::SPI3, Async>) {
|
||||
for n in 0u32.. {
|
||||
let mut write: String<128> = String::new();
|
||||
let mut read = [0; 128];
|
||||
core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
// transfer will slice the &mut read down to &write's actual length.
|
||||
spi.transfer(&mut read, write.as_bytes()).await.ok();
|
||||
info!("read via spi+dma: {}", from_utf8(&read).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let mut spi_config = spi::Config::default();
|
||||
spi_config.frequency = mhz(1);
|
||||
|
||||
let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, p.GPDMA1_CH0, p.GPDMA1_CH1, spi_config);
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
|
||||
executor.run(|spawner| {
|
||||
unwrap!(spawner.spawn(main_task(spi)));
|
||||
})
|
||||
}
|
39
examples/stm32h7rs/src/bin/usart.rs
Normal file
39
examples/stm32h7rs/src/bin/usart.rs
Normal file
@ -0,0 +1,39 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::usart::{Config, Uart};
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task() {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let config = Config::default();
|
||||
let mut usart = Uart::new_blocking(p.UART7, p.PF6, p.PF7, config).unwrap();
|
||||
|
||||
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
|
||||
info!("wrote Hello, starting echo");
|
||||
|
||||
let mut buf = [0u8; 1];
|
||||
loop {
|
||||
unwrap!(usart.blocking_read(&mut buf));
|
||||
unwrap!(usart.blocking_write(&buf));
|
||||
}
|
||||
}
|
||||
|
||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
|
||||
executor.run(|spawner| {
|
||||
unwrap!(spawner.spawn(main_task()));
|
||||
})
|
||||
}
|
47
examples/stm32h7rs/src/bin/usart_dma.rs
Normal file
47
examples/stm32h7rs/src/bin/usart_dma.rs
Normal file
@ -0,0 +1,47 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::*;
|
||||
use embassy_executor::Executor;
|
||||
use embassy_stm32::usart::{Config, Uart};
|
||||
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||
use heapless::String;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||
});
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task() {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let config = Config::default();
|
||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config).unwrap();
|
||||
|
||||
for n in 0u32.. {
|
||||
let mut s: String<128> = String::new();
|
||||
core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
|
||||
|
||||
usart.write(s.as_bytes()).await.ok();
|
||||
|
||||
info!("wrote DMA");
|
||||
}
|
||||
}
|
||||
|
||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
|
||||
executor.run(|spawner| {
|
||||
unwrap!(spawner.spawn(main_task()));
|
||||
})
|
||||
}
|
48
examples/stm32h7rs/src/bin/usart_split.rs
Normal file
48
examples/stm32h7rs/src/bin/usart_split.rs
Normal file
@ -0,0 +1,48 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::mode::Async;
|
||||
use embassy_stm32::peripherals::UART7;
|
||||
use embassy_stm32::usart::{Config, Uart, UartRx};
|
||||
use embassy_stm32::{bind_interrupts, peripherals, usart};
|
||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
UART7 => usart::InterruptHandler<peripherals::UART7>;
|
||||
});
|
||||
|
||||
static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new();
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) -> ! {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let config = Config::default();
|
||||
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config).unwrap();
|
||||
unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
|
||||
|
||||
let (mut tx, rx) = usart.split();
|
||||
|
||||
unwrap!(spawner.spawn(reader(rx)));
|
||||
|
||||
loop {
|
||||
let buf = CHANNEL.receive().await;
|
||||
info!("writing...");
|
||||
unwrap!(tx.write(&buf).await);
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: UartRx<'static, UART7, Async>) {
|
||||
let mut buf = [0; 8];
|
||||
loop {
|
||||
info!("reading...");
|
||||
unwrap!(rx.read(&mut buf).await);
|
||||
CHANNEL.send(buf).await;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
runner = "teleprobe client run"
|
||||
#runner = "teleprobe local run --chip STM32F103C8 --elf"
|
||||
#runner = "teleprobe local run --chip STM32H7S3L8Hx --elf"
|
||||
|
||||
rustflags = [
|
||||
# Code-size optimizations.
|
||||
|
@ -32,6 +32,7 @@ stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng", "hash"]
|
||||
stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
|
||||
stm32f091rc = ["embassy-stm32/stm32f091rc", "cm0", "not-gpdma", "chrono"]
|
||||
stm32h503rb = ["embassy-stm32/stm32h503rb", "rng", "stop"]
|
||||
stm32h7s3l8 = ["embassy-stm32/stm32h7s3l8", "rng", "cordic", "hash"] # TODO: fdcan crashes, cryp dma hangs.
|
||||
|
||||
cryp = []
|
||||
hash = []
|
||||
|
@ -67,7 +67,12 @@ async fn main(_spawner: Spawner) {
|
||||
#[cfg(feature = "stm32g491re")]
|
||||
let (mut write_dma, mut read_dma) = (dp.DMA1_CH4, dp.DMA1_CH5);
|
||||
|
||||
#[cfg(any(feature = "stm32h563zi", feature = "stm32u585ai", feature = "stm32u5a5zj"))]
|
||||
#[cfg(any(
|
||||
feature = "stm32h563zi",
|
||||
feature = "stm32u585ai",
|
||||
feature = "stm32u5a5zj",
|
||||
feature = "stm32h7s3l8"
|
||||
))]
|
||||
let (mut write_dma, mut read_dma) = (dp.GPDMA1_CH0, dp.GPDMA1_CH1);
|
||||
|
||||
// calculate first result using blocking mode
|
||||
|
@ -74,6 +74,20 @@ fn options() -> (Config, TestOptions) {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32h7s3l8"))]
|
||||
fn options() -> (Config, TestOptions) {
|
||||
use embassy_stm32::rcc;
|
||||
let mut c = config();
|
||||
c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
|
||||
(
|
||||
c,
|
||||
TestOptions {
|
||||
max_latency: Duration::from_micros(1200),
|
||||
max_buffered: 3,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))]
|
||||
fn options() -> (Config, TestOptions) {
|
||||
info!("G4 config");
|
||||
|
@ -216,7 +216,12 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
|
||||
fn delay() {
|
||||
#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h7a3zi"))]
|
||||
#[cfg(any(
|
||||
feature = "stm32h755zi",
|
||||
feature = "stm32h753zi",
|
||||
feature = "stm32h7a3zi",
|
||||
feature = "stm32h7s3l8"
|
||||
))]
|
||||
cortex_m::asm::delay(9000);
|
||||
cortex_m::asm::delay(1000);
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ bind_interrupts!(struct Irqs {
|
||||
feature = "stm32h563zi",
|
||||
feature = "stm32h503rb",
|
||||
feature = "stm32u5a5zj",
|
||||
feature = "stm32u585ai"
|
||||
feature = "stm32u585ai",
|
||||
feature = "stm32h7s3l8"
|
||||
))]
|
||||
bind_interrupts!(struct Irqs {
|
||||
HASH => hash::InterruptHandler<peripherals::HASH>;
|
||||
|
@ -60,6 +60,8 @@ teleprobe_meta::target!(b"nucleo-stm32wba52cg");
|
||||
teleprobe_meta::target!(b"nucleo-stm32f091rc");
|
||||
#[cfg(feature = "stm32h503rb")]
|
||||
teleprobe_meta::target!(b"nucleo-stm32h503rb");
|
||||
#[cfg(feature = "stm32h7s3l8")]
|
||||
teleprobe_meta::target!(b"nucleo-stm32h7s3l8");
|
||||
|
||||
macro_rules! define_peris {
|
||||
($($name:ident = $peri:ident,)* $(@irq $irq_name:ident = $irq_code:tt,)*) => {
|
||||
@ -249,6 +251,13 @@ define_peris!(
|
||||
SPI = SPI1, SPI_SCK = PB4, SPI_MOSI = PA15, SPI_MISO = PB3, SPI_TX_DMA = GPDMA1_CH0, SPI_RX_DMA = GPDMA1_CH1,
|
||||
@irq UART = {LPUART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::LPUART1>;},
|
||||
);
|
||||
#[cfg(feature = "stm32h7s3l8")]
|
||||
define_peris!(
|
||||
CRYP_IN_DMA = GPDMA1_CH0, CRYP_OUT_DMA = GPDMA1_CH1,
|
||||
UART = USART1, UART_TX = PB14, UART_RX = PA10, UART_TX_DMA = GPDMA1_CH0, UART_RX_DMA = GPDMA1_CH1,
|
||||
SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = GPDMA1_CH0, SPI_RX_DMA = GPDMA1_CH1,
|
||||
@irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
|
||||
);
|
||||
|
||||
pub fn config() -> Config {
|
||||
#[allow(unused_mut)]
|
||||
@ -641,6 +650,28 @@ pub fn config() -> Config {
|
||||
});
|
||||
config.rcc.sys = Sysclk::PLL1_R;
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32h7s3l8"))]
|
||||
{
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(24_000_000),
|
||||
mode: HseMode::Oscillator,
|
||||
});
|
||||
config.rcc.pll1 = Some(Pll {
|
||||
source: PllSource::HSE,
|
||||
prediv: PllPreDiv::DIV3,
|
||||
mul: PllMul::MUL150,
|
||||
divp: Some(PllDiv::DIV2), // 600Mhz
|
||||
divq: Some(PllDiv::DIV25), // 48Mhz
|
||||
divr: None,
|
||||
});
|
||||
config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
|
||||
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz
|
||||
config.rcc.apb1_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb2_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.apb5_pre = APBPrescaler::DIV2; // 150 Mhz
|
||||
config.rcc.voltage_scale = VoltageScale::HIGH;
|
||||
config.rcc.mux.spi1sel = mux::Spi123sel::PLL1_Q;
|
||||
}
|
||||
config
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user