Compare commits

...

23 Commits

Author SHA1 Message Date
03325ea81b update embedded-storage{,-async}, remove patch. 2023-12-04 13:48:36 +01:00
52fabbfb46 Merge pull request #2224 from cbruiz/stm32g0-usb_spi
Add support for HSE Oscillator in stm32g0
2023-12-04 12:32:52 +00:00
09592ffa6a stm32/rcc: Add support for HSE Oscillator in stm32g0 2023-12-04 13:28:00 +01:00
b867f9b5b6 Merge pull request #2241 from adamgreig/stm32-uid
STM32: Add UID driver
2023-12-03 23:22:57 +00:00
198ef8183e STM32: Add UID driver 2023-12-03 23:17:49 +00:00
696c703b8c Merge pull request #2237 from badrbouslikhin/main
stm32/rcc: make h7 rm0399 power supply configurable
2023-12-03 22:47:34 +00:00
521cdef8a1 Merge pull request #2245 from peter9477/nrf52-qspi-zerolen-fix
nrf52/qspi: avoid infinite busy-wait read/write with zero-len buf
2023-12-03 23:21:32 +01:00
1dc31c4627 Merge pull request #2244 from embassy-rs/rm-xtensa
executor: remove arch-xtensa.
2023-12-03 23:21:17 +01:00
9fb2eb7470 nrf52/qspi: avoid infinite busy-wait on QSPI read/write with zero-len buffer, fixes #2115 2023-12-03 16:35:39 -05:00
ca3891bb8c executor: remove arch-xtensa.
It's been broken for months and nobody has noticed. The `esp*-hal` crates have
much better support.

Fixes #2234
Closes  #1912
2023-12-03 22:33:27 +01:00
9ba3aeada4 Merge pull request #2243 from peter9477/nrf52-approtect-fix
minimum build code for new APPROTECT is chip type-specific
2023-12-03 20:27:02 +00:00
dd62bb16e5 minimum build code for new APPROTECT is chip type-specific 2023-12-03 13:47:26 -05:00
ea43d74780 stm32/rcc: add missing h7 power config 2023-12-02 14:55:00 +01:00
22c39fd697 stm32/rcc: refactor h7 rm0455,rm0468 and rm0468 power management 2023-12-02 14:47:36 +01:00
87c0f1525d stm32/rcc: enable power supply configurability for rm0455 and rm0468 2023-12-02 14:45:36 +01:00
a31ae52d1a Merge pull request #2240 from GrantM11235/fix-freq-off-by-one
stm32/timer: Fix frequency off-by-one
2023-12-02 08:13:50 +00:00
8c0e2748db stm32/timer: Fix frequency off-by-one 2023-12-01 22:09:15 -06:00
ce4dd67f3b Merge pull request #2236 from tshepang/patch-2
no_std and no_main can be used on stable
2023-12-01 18:10:27 +01:00
929fd551de Merge pull request #2235 from tshepang/patch-1
runtime.adoc: typo
2023-12-01 18:10:15 +01:00
c97f65ac60 stm32/rcc: make h7 rm0399 power supply configurable 2023-12-01 15:05:31 +01:00
33cfef871d no_std and no_main can be used on stable 2023-12-01 11:56:35 +02:00
270504d87d runtime.adoc: typo 2023-12-01 08:45:20 +02:00
fe8c46bce3 Merge pull request #2218 from embassy-rs/stable2
Remove nightly and unstable-traits features in preparation for 1.75.
2023-11-29 17:50:09 +01:00
45 changed files with 262 additions and 147 deletions

View File

@ -1,3 +0,0 @@
[patch.crates-io]
embedded-storage = { git = "https://github.com/rust-embedded-community/embedded-storage", rev = "634302740f8d676538c3890748e7d7dfe372a040" }
embedded-storage-async = { git = "https://github.com/rust-embedded-community/embedded-storage", rev = "634302740f8d676538c3890748e7d7dfe372a040" }

View File

@ -6,13 +6,22 @@ So you've got one of the xref:examples.adoc[examples] running, but what now? Let
The full example can be found link:https://github.com/embassy-rs/embassy/tree/master/docs/modules/ROOT/examples/basic[here].
=== Rust Nightly
=== Bare metal
The first thing you'll notice is a few declarations stating that Embassy requires some nightly features:
The first thing you'll notice is a few declarations, two of which indicate that Embassy is suitable for bare metal development:
[source,rust]
----
include::example$basic/src/main.rs[lines="1..3"]
include::example$basic/src/main.rs[lines="1..2"]
----
=== Rust Nightly
The next declaration is a Rust Unstable feature, which means that Embassy requires Rust Nightly:
[source,rust]
----
include::example$basic/src/main.rs[lines="3"]
----
=== Dealing with errors

View File

@ -27,7 +27,7 @@ If you use the `#[embassy_executor::main]` macro in your application, it creates
Interrupts are a common way for peripherals to signal completion of some operation and fits well with the async execution model. The following diagram describes a typical application flow where (1) a task is polled and is attempting to make progress. The task then (2) instructs the peripheral to perform some operation, and awaits. After some time has passed, (3) an interrupt is raised, marking the completion of the operation.
The peripheral HAL then (4) ensures that interrupt signals are routed to to the peripheral and updating the peripheral state with the results of the operation. The executor is then (5) notified that the task should be polled, which it will do.
The peripheral HAL then (4) ensures that interrupt signals are routed to the peripheral and updating the peripheral state with the results of the operation. The executor is then (5) notified that the task should be polled, which it will do.
image::embassy_irq.png[Interrupt handling]

View File

@ -29,8 +29,8 @@ log = { version = "0.4", optional = true }
ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true }
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
embassy-sync = { version = "0.4.0", path = "../../embassy-sync" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true }
signature = { version = "1.6.4", default-features = false }

View File

@ -21,8 +21,8 @@ embassy-nrf = { path = "../../embassy-nrf" }
embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" }
cortex-m-rt = { version = "0.7" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
cfg-if = "1.0.0"
nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true }

View File

@ -24,8 +24,8 @@ embassy-time = { path = "../../embassy-time" }
cortex-m = { version = "0.7.6" }
cortex-m-rt = { version = "0.7" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
cfg-if = "1.0.0"
[features]

View File

@ -23,8 +23,8 @@ embassy-stm32 = { path = "../../embassy-stm32", default-features = false }
embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" }
cortex-m-rt = { version = "0.7" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
cfg-if = "1.0.0"
[features]

View File

@ -25,8 +25,8 @@ embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
] }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.2" }
embedded-hal-async = { version = "=1.0.0-rc.2" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
nb = "1.0.0"
defmt = { version = "0.3", optional = true }

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
- Removed `arch-xtensa`. Use the executor provided by the HAL crate (`esp-hal`, `esp32s3-hal`, etc...) instead.
## 0.3.3 - 2023-11-15
- Add `main` macro reexport for Xtensa arch.

View File

@ -57,7 +57,6 @@ critical-section = { version = "1.1", features = ["std"] }
_arch = [] # some arch was picked
arch-std = ["_arch", "critical-section/std"]
arch-cortex-m = ["_arch", "dep:cortex-m"]
arch-xtensa = ["_arch"]
arch-riscv32 = ["_arch", "dep:portable-atomic"]
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]

View File

@ -1,89 +0,0 @@
#[cfg(feature = "executor-interrupt")]
compile_error!("`executor-interrupt` is not supported with `arch-xtensa`.");
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
pub use embassy_macros::main_riscv as main;
use crate::{raw, Spawner};
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
#[export_name = "__pender"]
fn __pender(_context: *mut ()) {
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
}
/// Xtensa Executor
pub struct Executor {
inner: raw::Executor,
not_send: PhantomData<*mut ()>,
}
impl Executor {
/// Create a new Executor.
pub fn new() -> Self {
Self {
inner: raw::Executor::new(core::ptr::null_mut()),
not_send: PhantomData,
}
}
/// Run the executor.
///
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
/// this executor. Use it to spawn the initial task(s). After `init` returns,
/// the executor starts running the tasks.
///
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
/// for example by passing it as an argument to the initial tasks.
///
/// This function requires `&'static mut self`. This means you have to store the
/// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this:
///
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
///
/// This function never returns.
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
init(self.inner.spawner());
loop {
unsafe {
self.inner.poll();
// Manual critical section implementation that only masks interrupts handlers.
// We must not acquire the cross-core on dual-core systems because that would
// prevent the other core from doing useful work while this core is sleeping.
let token: critical_section::RawRestoreState;
core::arch::asm!("rsil {0}, 5", out(reg) token);
// we do not care about race conditions between the load and store operations, interrupts
// will only set this value to true.
// if there is work to do, loop back to polling
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
core::arch::asm!(
"wsr.ps {0}",
"rsync", in(reg) token)
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing
// PS.INTLEVEL the critical section ends here
// take care not add code after `waiti` if it needs to be inside the CS
core::arch::asm!("waiti 0"); // critical section ends here
}
}
}
}
}
}

View File

@ -1,5 +1,4 @@
#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)]
#![cfg_attr(feature = "arch-xtensa", feature(asm_experimental_arch))]
#![allow(clippy::new_without_default)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
@ -21,12 +20,11 @@ macro_rules! check_at_most_one {
check_at_most_one!(@amo [$($f)*] [$($f)*] []);
};
}
check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-xtensa", "arch-std", "arch-wasm",);
check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",);
#[cfg(feature = "_arch")]
#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")]
#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")]
#[cfg_attr(feature = "arch-xtensa", path = "arch/xtensa.rs")]
#[cfg_attr(feature = "arch-std", path = "arch/std.rs")]
#[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")]
mod arch;

View File

@ -106,7 +106,7 @@ cortex-m = "0.7.6"
critical-section = "1.1"
rand_core = "0.6.3"
fixed = "1.10.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
embedded-storage-async = "0.4.0"
cfg-if = "1.0.0"

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'E';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 256 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'D';
embassy_hal_internal::peripherals! {
// USB

View File

@ -11,6 +11,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 255;
pub const FLASH_SIZE: usize = 512 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'G';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 512 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// USB

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 1024 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'F';
embassy_hal_internal::peripherals! {
// USB

View File

@ -349,10 +349,11 @@ pub fn init(config: config::Config) -> Peripherals {
// Get the letter for the build code (b'A' .. b'F')
let build_code = (variant >> 8) as u8;
if build_code >= b'F' {
// Chips with build code F and higher (revision 3 and higher) have an
if build_code >= chip::APPROTECT_MIN_BUILD_CODE {
// Chips with a certain chip type-specific build code or higher have an
// improved APPROTECT ("hardware and software controlled access port protection")
// which needs explicit action by the firmware to keep it unlocked
// See https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect
// UICR.APPROTECT = SwDisabled
let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);

20
embassy-nrf/src/qspi.rs Normal file → Executable file
View File

@ -393,6 +393,11 @@ impl<'d, T: Instance> Qspi<'d, T> {
/// against the flash capacity. It is intended for use when QSPI is used as
/// a raw bus, not with flash memory.
pub async fn read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
// Avoid blocking_wait_ready() blocking forever on zero-length buffers.
if data.len() == 0 {
return Ok(());
}
let ondrop = OnDrop::new(Self::blocking_wait_ready);
self.start_read(address, data)?;
@ -409,6 +414,11 @@ impl<'d, T: Instance> Qspi<'d, T> {
/// against the flash capacity. It is intended for use when QSPI is used as
/// a raw bus, not with flash memory.
pub async fn write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
// Avoid blocking_wait_ready() blocking forever on zero-length buffers.
if data.len() == 0 {
return Ok(());
}
let ondrop = OnDrop::new(Self::blocking_wait_ready);
self.start_write(address, data)?;
@ -425,6 +435,11 @@ impl<'d, T: Instance> Qspi<'d, T> {
/// against the flash capacity. It is intended for use when QSPI is used as
/// a raw bus, not with flash memory.
pub fn blocking_read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> {
// Avoid blocking_wait_ready() blocking forever on zero-length buffers.
if data.len() == 0 {
return Ok(());
}
self.start_read(address, data)?;
Self::blocking_wait_ready();
Ok(())
@ -436,6 +451,11 @@ impl<'d, T: Instance> Qspi<'d, T> {
/// against the flash capacity. It is intended for use when QSPI is used as
/// a raw bus, not with flash memory.
pub fn blocking_write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> {
// Avoid blocking_wait_ready() blocking forever on zero-length buffers.
if data.len() == 0 {
return Ok(());
}
self.start_write(address, data)?;
Self::blocking_wait_ready();
Ok(())

View File

@ -71,7 +71,7 @@ chrono = { version = "0.4", default-features = false, optional = true }
embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
embedded-storage = { version = "0.3" }
embedded-storage-async = { version = "0.4.0" }
embedded-storage-async = { version = "0.4.1" }
rand_core = "0.6.4"
fixed = "1.23.1"

View File

@ -46,8 +46,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.2" }
embedded-hal-async = { version = "=1.0.0-rc.2" }
embedded-hal-nb = { version = "=1.0.0-rc.2" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0" }
embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" }
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }

View File

@ -63,6 +63,8 @@ pub mod sai;
pub mod sdmmc;
#[cfg(spi)]
pub mod spi;
#[cfg(uid)]
pub mod uid;
#[cfg(usart)]
pub mod usart;
#[cfg(usb)]

View File

@ -10,10 +10,18 @@ use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1)
Bypass,
}
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
HSE(Hertz),
HSE(Hertz, HseMode),
HSI(HSIPrescaler),
PLL(PllConfig),
LSI,
@ -61,7 +69,7 @@ impl Default for PllConfig {
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum PllSource {
HSI,
HSE(Hertz),
HSE(Hertz, HseMode),
}
/// Clocks configutation
@ -90,7 +98,7 @@ impl PllConfig {
pub(crate) fn init(self) -> Hertz {
let (src, input_freq) = match self.source {
PllSource::HSI => (vals::Pllsrc::HSI, HSI_FREQ),
PllSource::HSE(freq) => (vals::Pllsrc::HSE, freq),
PllSource::HSE(freq, _) => (vals::Pllsrc::HSE, freq),
};
let m_freq = input_freq / self.m;
@ -125,8 +133,11 @@ impl PllConfig {
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
PllSource::HSE(_) => {
RCC.cr().write(|w| w.set_hseon(true));
PllSource::HSE(_, mode) => {
RCC.cr().write(|w| {
w.set_hsebyp(mode != HseMode::Oscillator);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
}
}
@ -177,9 +188,12 @@ pub(crate) unsafe fn init(config: Config) {
(HSI_FREQ / div, Sw::HSI)
}
ClockSrc::HSE(freq) => {
ClockSrc::HSE(freq, mode) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
RCC.cr().write(|w| {
w.set_hseon(true);
w.set_hsebyp(mode != HseMode::Oscillator);
});
while !RCC.cr().read().hserdy() {}
(freq, Sw::HSE)

View File

@ -117,6 +117,75 @@ impl From<TimerPrescaler> for Timpre {
}
}
/// Power supply configuration
/// See RM0433 Rev 4 7.4
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
#[derive(PartialEq)]
pub enum SupplyConfig {
/// Default power supply configuration.
/// V CORE Power Domains are supplied from the LDO according to VOS.
/// SMPS step-down converter enabled at 1.2V, may be used to supply the LDO.
Default,
/// Power supply configuration using the LDO.
/// V CORE Power Domains are supplied from the LDO according to VOS.
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter disabled.
LDO,
/// Power supply configuration directly from the SMPS step-down converter.
/// V CORE Power Domains are supplied from SMPS step-down converter according to VOS.
/// LDO bypassed.
/// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
DirectSMPS,
/// Power supply configuration from the SMPS step-down converter, that supplies the LDO.
/// V CORE Power Domains are supplied from the LDO according to VOS
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter enabled according to SDLEVEL, and supplies the LDO.
/// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
SMPSLDO(SMPSSupplyVoltage),
/// Power supply configuration from SMPS supplying external circuits and potentially the LDO.
/// V CORE Power Domains are supplied from voltage regulator according to VOS
/// LDO power mode (Main, LP, Off) will follow system low-power modes.
/// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the LDO.
/// SMPS step-down converter forced ON in MR mode.
SMPSExternalLDO(SMPSSupplyVoltage),
/// Power supply configuration from SMPS supplying external circuits and bypassing the LDO.
/// V CORE supplied from external source
/// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the external source for V CORE .
/// SMPS step-down converter forced ON in MR mode.
SMPSExternalLDOBypass(SMPSSupplyVoltage),
/// Power supply configuration from an external source, SMPS disabled and the LDO bypassed.
/// V CORE supplied from external source
/// SMPS step-down converter disabled and LDO bypassed, voltage monitoring still active.
SMPSDisabledLDOBypass,
}
/// 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))]
#[derive(PartialEq)]
pub enum SMPSSupplyVoltage {
V1_8,
V2_5,
}
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
impl SMPSSupplyVoltage {
/// Convert SMPSSupplyVoltage to u8 representation.
fn to_u8(&self) -> u8 {
match self {
SMPSSupplyVoltage::V1_8 => 0b01,
SMPSSupplyVoltage::V2_5 => 0b10,
}
}
}
/// Configuration of the core clocks
#[non_exhaustive]
pub struct Config {
@ -144,6 +213,9 @@ pub struct Config {
pub timer_prescaler: TimerPrescaler,
pub voltage_scale: VoltageScale,
pub ls: super::LsConfig,
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
pub supply_config: SupplyConfig,
}
impl Default for Config {
@ -177,6 +249,9 @@ impl Default for Config {
timer_prescaler: TimerPrescaler::DefaultX2,
voltage_scale: VoltageScale::Scale0,
ls: Default::default(),
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
supply_config: SupplyConfig::Default,
}
}
}
@ -195,12 +270,58 @@ pub(crate) unsafe fn init(config: Config) {
});
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
PWR.cr3().modify(|w| {
// hardcode "Direct SPMS" for now, this is what works on nucleos with the
// default solderbridge configuration.
w.set_sden(true);
w.set_ldoen(false);
});
{
match config.supply_config {
SupplyConfig::Default => {
PWR.cr3().modify(|w| {
w.set_sdlevel(0b00);
w.set_sdexthp(false);
w.set_sden(true);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::LDO => {
PWR.cr3().modify(|w| {
w.set_sden(false);
w.set_ldoen(true);
w.set_bypass(false);
});
}
SupplyConfig::DirectSMPS => {
PWR.cr3().modify(|w| {
w.set_sdexthp(false);
w.set_sden(true);
w.set_ldoen(false);
w.set_bypass(false);
});
}
SupplyConfig::SMPSLDO(ref smps_supply_voltage)
| SupplyConfig::SMPSExternalLDO(ref smps_supply_voltage)
| SupplyConfig::SMPSExternalLDOBypass(ref smps_supply_voltage) => {
PWR.cr3().modify(|w| {
w.set_sdlevel(smps_supply_voltage.to_u8());
w.set_sdexthp(matches!(
config.supply_config,
SupplyConfig::SMPSExternalLDO(_) | SupplyConfig::SMPSExternalLDOBypass(_)
));
w.set_sden(true);
w.set_ldoen(matches!(
config.supply_config,
SupplyConfig::SMPSLDO(_) | SupplyConfig::SMPSExternalLDO(_)
));
w.set_bypass(matches!(config.supply_config, SupplyConfig::SMPSExternalLDOBypass(_)));
});
}
SupplyConfig::SMPSDisabledLDOBypass => {
PWR.cr3().modify(|w| {
w.set_sden(false);
w.set_ldoen(false);
w.set_bypass(true);
});
}
}
}
// Validate the supply configuration. If you are stuck here, it is
// because the voltages on your board do not match those specified

View File

@ -46,7 +46,10 @@ pub(crate) mod sealed {
assert!(f > 0);
let pclk_ticks_per_timer_period = timer_f / f;
let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1);
// the timer counts `0..=arr`, we want it to count `0..divide_by`
let arr = unwrap!(u16::try_from(divide_by - 1));
let regs = Self::regs();
regs.psc().write(|r| r.set_psc(psc));

29
embassy-stm32/src/uid.rs Normal file
View File

@ -0,0 +1,29 @@
/// Get this device's unique 96-bit ID.
pub fn uid() -> &'static [u8; 12] {
unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() }
}
/// Get this device's unique 96-bit ID, encoded into a string of 24 hexadecimal ASCII digits.
pub fn uid_hex() -> &'static str {
unsafe { core::str::from_utf8_unchecked(uid_hex_bytes()) }
}
/// Get this device's unique 96-bit ID, encoded into 24 hexadecimal ASCII bytes.
pub fn uid_hex_bytes() -> &'static [u8; 24] {
const HEX: &[u8; 16] = b"0123456789ABCDEF";
static mut UID_HEX: [u8; 24] = [0; 24];
static mut LOADED: bool = false;
critical_section::with(|_| unsafe {
if !LOADED {
let uid = uid();
for (idx, v) in uid.iter().enumerate() {
let lo = v & 0x0f;
let hi = (v & 0xf0) >> 4;
UID_HEX[idx * 2] = HEX[hi as usize];
UID_HEX[idx * 2 + 1] = HEX[lo as usize];
}
LOADED = true;
}
});
unsafe { &UID_HEX }
}

View File

@ -20,7 +20,7 @@ embedded-hal = { version = "0.2.6" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
[features]
default = ["panic-reset"]

View File

@ -16,7 +16,7 @@ defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"

View File

@ -16,7 +16,7 @@ defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
panic-reset = { version = "0.1.1" }
embedded-hal = { version = "0.2.6" }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"

View File

@ -16,7 +16,7 @@ embassy-time = { path = "../../../../embassy-time", features = [] }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = { version = "0.7" }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
embedded-storage-async = "0.4.0"
cfg-if = "1.0.0"

View File

@ -14,7 +14,7 @@ embassy-boot-stm32 = { path = "../../../../embassy-boot/stm32" }
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
embassy-sync = { version = "0.4.0", path = "../../../../embassy-sync" }
cortex-m-rt = { version = "0.7" }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
embedded-storage-async = "0.4.0"
cfg-if = "1.0.0"

View File

@ -33,7 +33,7 @@ cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
rand = { version = "0.8.4", default-features = false }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
usbd-hid = "0.6.0"
serde = { version = "1.0.136", default-features = false }
embedded-hal = { version = "1.0.0-rc.2" }

View File

@ -23,7 +23,7 @@ cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
rand = { version = "0.8.4", default-features = false }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
usbd-hid = "0.6.0"
serde = { version = "1.0.136", default-features = false }

View File

@ -23,7 +23,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
static_cell = { version = "2", features = ["nightly"]}
[profile.release]

View File

@ -22,5 +22,5 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
static_cell = { version = "2", features = ["nightly"]}

View File

@ -25,7 +25,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
micromath = "2.0.0"
static_cell = { version = "2", features = ["nightly"]}
chrono = { version = "^0.4", default-features = false}

View File

@ -26,7 +26,7 @@ heapless = { version = "0.8", default-features = false }
nb = "1.0.0"
rand_core = "0.6.3"
critical-section = "1.1"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
static_cell = { version = "2", features = ["nightly"]}
[profile.release]

View File

@ -30,7 +30,7 @@ rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
static_cell = { version = "2", features = ["nightly"]}
# cargo build/run

View File

@ -30,7 +30,7 @@ rand_core = "0.6.3"
critical-section = "1.1"
micromath = "2.0.0"
stm32-fmc = "0.3.0"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
static_cell = { version = "2", features = ["nightly"]}
chrono = { version = "^0.4", default-features = false }

View File

@ -18,7 +18,7 @@ embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["de
defmt = "0.3"
defmt-rtt = "0.4"
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }

View File

@ -19,7 +19,7 @@ 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.8", default-features = false }
embedded-storage = "0.3.0"
embedded-storage = "0.3.1"
[profile.release]
debug = 2

View File

@ -18,7 +18,7 @@ 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-storage = "0.3.0"
embedded-storage = "0.3.1"
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
heapless = { version = "0.8", default-features = false }