AlyoshaVasilieva/imxrt1062-trng 1
iMXRT1062 TRNG
AlyoshaVasilieva/at-commands 0
Rust project for building and parsing at commands
To compute CRC values by providing the length of bits, expression, reflection, an initial value and a final xor value. It has built-in CRC-8-ATM, CRC-8-CDMA, CRC-16-IBM, CRC16-CCITT, CRC-32-IEEE, CRC-32-C, CRC-64-ISO and CRC-64-ECMA functions.
AlyoshaVasilieva/epub-builder 0
A Rust library for generating EPUB files
Rust for NXP i.MX RT
Lolcate -- A comically fast way of indexing and querying your filesystem. Replaces locate / mlocate / updatedb. Written in Rust.
Winsen Infrared CO2 Module MH-Z19 serial "api" implementation in Rust.
A debugging toolset and library for debugging embedded ARM and RISC-V targets on a separate host
Run embedded programs just like native ones
Embedded Rust device crates for STM32 microcontrollers
pull request commentstm32-rs/stm32f4xx-hal
@therealprof What else is needed from me at this point?
comment created time in a day
pull request commentstm32-rs/stm32h7xx-hal
Implement DMA for constant source buffers
I don't think the type parameter is too much to ask. I'll give the const-buffer changes some test usage. Thanks for getting this together!
comment created time in a day
issue commentrust-embedded/embedded-hal
Shared type definitions (e.g. MHz, bps...)
I would love to see the same happen for https://github.com/stm32-rs/stm32l4xx-hal
comment created time in a day
pull request commentstm32-rs/stm32-rs
Rename SP3EN to SPI3EN for G4 Family
TwoHandzcomment created time in 2 days
PR opened stm32-rs/stm32-rs
Closes #480.
Modifies SP3EN to SPI3EN for APB1ENR1 register for the G4 Family.
pr created time in 2 days
pull request commentstm32-rs/stm32h7xx-hal
Implement DMA based on embedded-dma traits
Breaking change: Added additional generic type on Transfer
. See #178
comment created time in 2 days
push eventstm32-rs/stm32h7xx-hal
commit sha b40f13e5b4112d1ef700b5f3869d959957a79c2d
Implement DMA for constant source buffers The lack of support for constant source buffers was first raised by @ryan-summers here https://github.com/stm32-rs/stm32h7xx-hal/pull/153#discussion_r515865869 This solution adds a 5th generic type parameter to `Transfer`, and uses this to implement transfer for two different type constraints on `BUF`. The additional generic type parameter will also be useful for MDMA support, which will also need its own versions of `init`, `next_transfer`, `next_transfer_with` and so on. The downside is the additional complexity of another type parameter
commit sha 2809fefadaa36c13bc2264548e7ca263873aa014
Add allow for clippy type_complexity with 5th type parameter
commit sha 1ac12e10f3f32393eca35c95e8bb9809038fe6f9
Merge pull request #178 from richardeoin/dma-const-buf1 Implement DMA for constant source buffers
push time in 2 days
PR merged stm32-rs/stm32h7xx-hal
The lack of support for constant source buffers was first raised by @ryan-summers here https://github.com/stm32-rs/stm32h7xx-hal/pull/153#discussion_r515865869
This solution adds a 5th generic type parameter to Transfer
, and uses this to implement Transfer
for two different type constraints on BUF
.
The additional generic type parameter will also be useful for MDMA support, which will also need its own versions of init
, next_transfer
, next_transfer_with
and so on.
The downside is the additional complexity of another type parameter.
pr closed time in 2 days
pull request commentstm32-rs/stm32h7xx-hal
Implement DMA for constant source buffers
Overall I think the additional type parameter is worth it for the extra flexibility it provides. Merging into dma
now, but still very open to receiving comments there
comment created time in 2 days
issue openedstm32-rs/stm32-rs
STM32G4 spi3en field mislabel sp3en
The svd files for the g4 family of devices labels the spi3en field of the apb1enr1 register as sp3en. This is inconsistent with the other SPI enable fields in the svd and the families datasheet.
created time in 3 days
Pull request review commentstm32-rs/stm32f4xx-hal
+//! # Controller Area Network (CAN) Interface+//!+//!+//! TX: Alternate Push-Pull Output+//! RX: Input Floating Input+//!+//! ### CAN1+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB9 |+//! | RX | PB8 |+//!+//! ### CAN2+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB13 |+//! | RX | PB12 |++use crate::bb;+use crate::gpio::{+ gpioa::{PA11, PA12},+ gpiob::{PB12, PB13, PB5, PB6, PB8, PB9},+ Alternate, AF9,+};+use crate::pac::{CAN1, CAN2};+use crate::rcc::APB1;++mod sealed {+ pub trait Sealed {}++ /// Bus associated to peripheral+ pub trait RccBus {+ /// Bus type;+ type Bus;+ }+}++pub trait Pins: sealed::Sealed {+ type Instance;+}++/*+ order: tx, rx similar to serial+*/++macro_rules! pins {+ ($($PER:ident => ($tx:ident, $rx:ident),)+) => {+ $(+ impl sealed::Sealed for ($tx<Alternate<AF9>>, $rx<Alternate<AF9>>) {}+ impl Pins for ($tx<Alternate<AF9>>, $rx<Alternate<AF9>>) {+ type Instance = $PER;+ }+ )++ }+}++pins! {+ CAN1 => (PA12, PA11),+ CAN1 => (PB9, PB8),+ CAN2 => (PB13, PB12),+ CAN2 => (PB6, PB5),+}++use sealed::RccBus;++/// Enable/disable peripheral+pub trait Enable: RccBus {+ fn enable(apb: &mut Self::Bus);+}++macro_rules! bus {+ ($($PER:ident => ($apbX:ty, $peren:literal),)+) => {+ $(+ impl RccBus for crate::pac::$PER {+ type Bus = $apbX;+ }+ impl Enable for crate::pac::$PER {+ #[inline(always)]+ fn enable(apb: &mut Self::Bus) {+ unsafe { bb::set(apb.enr(), $peren) };+ }+ }+ )++ }+}++bus! {+ CAN1 => (APB1, 25),+ CAN2 => (APB1, 26),+}++/// Interface to the CAN peripheral.+pub struct Can<Instance> {+ _peripheral: Instance,+}++impl<Instance> Can<Instance>+where+ Instance: Enable<Bus = APB1>,+{+ /// Creates a CAN interaface.+ pub fn new<P>(can: Instance, _pins: P, apb: &mut APB1) -> Can<Instance>
Its a common pattern to take ownership of the pins. For CAN it might be a bit too restrictive though: https://github.com/stm32-rs/stm32f1xx-hal/pull/215 (section Separate assign_pins())
comment created time in 3 days
Pull request review commentstm32-rs/stm32f4xx-hal
+//! # Controller Area Network (CAN) Interface+//!+//!+//! TX: Alternate Push-Pull Output+//! RX: Input Floating Input+//!+//! ### CAN1+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB9 |+//! | RX | PB8 |+//!+//! ### CAN2+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB13 |+//! | RX | PB12 |++use crate::bb;+use crate::gpio::{+ gpioa::{PA11, PA12},+ gpiob::{PB12, PB13, PB5, PB6, PB8, PB9},+ Alternate, AF9,+};+use crate::pac::{CAN1, CAN2};+use crate::rcc::APB1;++mod sealed {+ pub trait Sealed {}++ /// Bus associated to peripheral+ pub trait RccBus {+ /// Bus type;+ type Bus;+ }+}++pub trait Pins: sealed::Sealed {+ type Instance;+}++/*+ order: tx, rx similar to serial+*/++macro_rules! pins {+ ($($PER:ident => ($tx:ident, $rx:ident),)+) => {+ $(+ impl sealed::Sealed for ($tx<Alternate<AF9>>, $rx<Alternate<AF9>>) {}+ impl Pins for ($tx<Alternate<AF9>>, $rx<Alternate<AF9>>) {+ type Instance = $PER;+ }+ )++ }+}++pins! {
Quick look at the stm32f407 datasheet shows that the can signals can be mapped to even more pins (for larger packages).
comment created time in 3 days
Pull request review commentstm32-rs/stm32f4xx-hal
+//! # Controller Area Network (CAN) Interface+//!+//!+//! TX: Alternate Push-Pull Output+//! RX: Input Floating Input+//!+//! ### CAN1+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB9 |+//! | RX | PB8 |+//!+//! ### CAN2+//!+//! | Function | Pins |+//! |----------|-------|+//! | TX | PB13 |+//! | RX | PB12 |
Those tables do not fully reflect the pins defined on L59.
comment created time in 3 days
pull request commentstm32-rs/stm32f4xx-hal
While the RCC interface looks completely unlike everything else, I'd argue that it is less racy than the existing implementations which just do a read-modify-write cycle in a potentially multitasked (i.e., interrupts of different priority) application.
comment created time in 3 days
pull request commentstm32-rs/stm32f4xx-hal
Apparently I messed up and caused some warnings about unused fields on F410/413/423. I will create a follow-up PR for those.
comment created time in 3 days
Pull request review commentstm32-rs/stm32f4xx-hal
+//! Clock configuration.+//!+//! This module provides functionality to configure the RCC to generate the requested clocks.+//!+//! # Example+//!+//! ```+//! let dp = stm32::Peripherals::take().unwrap();+//! let clocks = rcc+//! .cfgr+//! .use_hse(8.mhz())+//! .sysclk(168.mhz())+//! .pclk1(24.mhz())+//! .i2s_clk(86.mhz())+//! .require_pll48clk()+//! .freeze();+//! // Test that the I2S clock is suitable for 48000KHz audio.+//! assert!(clocks.i2s_clk().unwrap() == 48.mhz().into());+//! ```+//!+//! # Limitations+//!+//! Unlike the clock configuration tool provided by ST, the code does not extensively search all+//! possible configurations. Instead, it often relies on an iterative approach to reduce+//! compitational complexity. On most MCUs the code will first generate a configuration for the 48+//! MHz clock and the system clock without taking other requested clocks into account, even if the+//! accuracy of these clocks is affected. **If you specific accuracy requirements, you should+//! always check the resulting frequencies!**+//!+//! Whereas the hardware often supports flexible clock source selection and many clocks can be+//! sourced from multiple PLLs, the code implements a fixed mapping between PLLs and clocks. The 48+//! MHz clock is always generated by the main PLL, the I2S clocks are always generated by the I2S+//! PLL (unless a matching external clock input is provided), and similarly the SAI clocks are+//! always generated by the SAI PLL. It is therefore not possible to, for example, specify two+//! different I2S frequencies unless you also provide a matching I2S_CKIN signal for one of them.+//!+//! Some MCUs have limited clock generation hardware and do not provide either I2S or SAI PLLs even+//! though I2S or SAI are available. On the STM32F410, the I2S clock is generated by the main PLL,+//! and on the STM32F413/423 SAI clocks are generated by the I2S PLL. On these MCUs, the actual+//! frequencies may substantially deviate from the requested frequencies.++use crate::stm32::rcc::cfgr::{HPRE_A, SW_A};+use crate::stm32::RCC;++use crate::time::Hertz;++#[cfg(not(feature = "stm32f410"))]+use pll::I2sPll;+use pll::MainPll;+#[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+))]+use pll::SaiPll;++mod pll;++/// Extension trait that constrains the `RCC` peripheral+pub trait RccExt {+ /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions+ fn constrain(self) -> Rcc;+}++impl RccExt for RCC {+ fn constrain(self) -> Rcc {+ Rcc {+ cfgr: CFGR {+ hse: None,+ hclk: None,+ pclk1: None,+ pclk2: None,+ sysclk: None,+ pll48clk: false,+ i2s_ckin: None,+ #[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ i2s_clk: None,+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ i2s_apb1_clk: None,+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ i2s_apb2_clk: None,+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ sai1_clk: None,+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ sai2_clk: None,+ },+ }+ }+}++/// Constrained RCC peripheral+pub struct Rcc {+ pub cfgr: CFGR,+}++/// Built-in high speed clock frequency+pub const HSI: u32 = 16_000_000; // Hz++#[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+))]+/// Minimum system clock frequency+pub const SYSCLK_MIN: u32 = 24_000_000;++#[cfg(any(feature = "stm32f446"))]+/// Minimum system clock frequency+pub const SYSCLK_MIN: u32 = 12_500_000;++#[cfg(feature = "stm32f401")]+/// Maximum system clock frequency+pub const SYSCLK_MAX: u32 = 84_000_000;++#[cfg(any(+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f415",+ feature = "stm32f417"+))]+/// Maximum system clock frequency+pub const SYSCLK_MAX: u32 = 168_000_000;++#[cfg(any(+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423"+))]+/// Maximum system clock frequency+pub const SYSCLK_MAX: u32 = 100_000_000;++#[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479"+))]+/// Maximum system clock frequency+pub const SYSCLK_MAX: u32 = 180_000_000;++#[cfg(any(+ feature = "stm32f401",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423"+))]+/// Maximum APB2 peripheral clock frequency+pub const PCLK2_MAX: u32 = SYSCLK_MAX;++#[cfg(not(any(+ feature = "stm32f401",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423"+)))]+/// Maximum APB2 peripheral clock frequency+pub const PCLK2_MAX: u32 = SYSCLK_MAX / 2;++/// Maximum APB1 peripheral clock frequency+pub const PCLK1_MAX: u32 = PCLK2_MAX / 2;++pub struct CFGR {+ hse: Option<u32>,+ hclk: Option<u32>,+ pclk1: Option<u32>,+ pclk2: Option<u32>,+ sysclk: Option<u32>,+ pll48clk: bool,++ i2s_ckin: Option<u32>,+ #[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ i2s_clk: Option<u32>,+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ i2s_apb1_clk: Option<u32>,+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ i2s_apb2_clk: Option<u32>,+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ sai1_clk: Option<u32>,+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ sai2_clk: Option<u32>,+}++impl CFGR {+ /// Uses HSE (external oscillator) instead of HSI (internal RC oscillator) as the clock source.+ /// Will result in a hang if an external oscillator is not connected or it fails to start.+ pub fn use_hse<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.hse = Some(freq.into().0);+ self+ }++ pub fn hclk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.hclk = Some(freq.into().0);+ self+ }++ pub fn pclk1<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.pclk1 = Some(freq.into().0);+ self+ }++ pub fn pclk2<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.pclk2 = Some(freq.into().0);+ self+ }++ pub fn sysclk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.sysclk = Some(freq.into().0);+ self+ }++ pub fn require_pll48clk(mut self) -> Self {+ self.pll48clk = true;+ self+ }++ /// Declares that the selected frequency is available at the I2S clock input pin (I2S_CKIN).+ ///+ /// If this frequency matches the requested SAI or I2S frequencies, the external I2S clock is+ /// used to generate the clocks.+ pub fn i2s_ckin<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.i2s_ckin = Some(freq.into().0);+ self+ }++ /// Selects an I2S clock frequency and enables the I2S clock.+ #[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ pub fn i2s_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.i2s_clk = Some(freq.into().0);+ self+ }++ /// Selects an I2S clock frequency for the first set of I2S instancesand enables the I2S clock.+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ pub fn i2s_apb1_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.i2s_apb1_clk = Some(freq.into().0);+ self+ }++ /// Selects an I2S clock frequency for the second set of I2S instances and enables the I2S clock.+ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ pub fn i2s_apb2_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.i2s_apb2_clk = Some(freq.into().0);+ self+ }++ /// Selects a SAIA clock frequency and enables the SAIA clock.+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ pub fn saia_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.sai1_clk = Some(freq.into().0);+ self+ }++ /// Selects a SAIB clock frequency and enables the SAIB clock.+ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ pub fn saib_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.sai2_clk = Some(freq.into().0);+ self+ }++ /// Selects a SAI1 clock frequency and enables the SAI1 clock.+ #[cfg(any(feature = "stm32f446",))]+ pub fn sai1_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.sai1_clk = Some(freq.into().0);+ self+ }++ /// Selects a SAI2 clock frequency and enables the SAI2 clock.+ #[cfg(any(feature = "stm32f446",))]+ pub fn sai2_clk<F>(mut self, freq: F) -> Self+ where+ F: Into<Hertz>,+ {+ self.sai2_clk = Some(freq.into().0);+ self+ }+ #[cfg(feature = "stm32f410")]+ #[inline(always)]+ fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {+ let i2s_clocks = self.i2s_clocks();++ let main_pll = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {+ // The I2S frequency is generated by the main PLL. The frequency needs to be accurate,+ // so we need an expensive full PLL configuration search.+ MainPll::setup_with_i2s(+ pllsrcclk,+ self.hse.is_some(),+ pllsysclk,+ self.pll48clk,+ i2s_clk,+ )+ } else {+ MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk)+ };++ PllSetup {+ use_pll: main_pll.use_pll,+ pllsysclk: main_pll.pllsysclk,+ pll48clk: main_pll.pll48clk,+ i2s: i2s_clocks.real(main_pll.plli2sclk, self.i2s_ckin),+ }+ }++ #[cfg(any(feature = "stm32f413", feature = "stm32f423"))]+ #[inline(always)]+ fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {+ let rcc = unsafe { &*RCC::ptr() };++ let i2s_clocks = self.i2s_clocks();+ let sai_clocks = self.sai_clocks();++ let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);++ let (i2s_pll, real_sai_clk) = if let Some(i2s_clk) = i2s_clocks.pll_i2s_clk {+ // Currently, we only support generating SAI/PLL clocks with the I2S PLL. This is only+ // really usable when the frequencies are identical or the I2S frequency is a multiple of+ // the SAI frequency. Therefore, we just optimize the PLL for the I2S frequency and then+ // derive the SAI frequency from the I2S frequency.+ let i2s_pll = I2sPll::setup(pllsrcclk, Some(i2s_clk));++ if let Some(sai_clk) = sai_clocks.pll_sai_clk {+ let div = u32::min(+ u32::max((i2s_pll.plli2sclk.unwrap() + (sai_clk >> 1)) / sai_clk, 1),+ 31,+ );+ rcc.dckcfgr.modify(|_, w| w.plli2sdivr().bits(div as u8));+ let real_sai_clk = sai_clk / div;+ (i2s_pll, Some(real_sai_clk))+ } else {+ (i2s_pll, None)+ }+ } else if let Some(pll_sai_clk) = sai_clocks.pll_sai_clk {+ // We try all divider values to get the best approximation of the requested frequency.+ // NOTE: STM32F413/423 have a different divider range than other models!+ let (i2s_pll, real_sai_clk, div) = (1..31)+ .map(|div| {+ let i2s_pll = I2sPll::setup(pllsrcclk, Some(pll_sai_clk * div));+ let real_clk = i2s_pll.plli2sclk.unwrap() / div;+ (i2s_pll, real_clk, div)+ })+ .min_by_key(|(_, real_clk, _)| (*real_clk as i32 - pll_sai_clk as i32).abs())+ .unwrap();+ rcc.dckcfgr.modify(|_, w| w.plli2sdivr().bits(div as u8));+ (i2s_pll, Some(real_sai_clk))+ } else {+ (I2sPll::unused(), None)+ };++ PllSetup {+ use_pll: main_pll.use_pll,+ use_i2spll: i2s_pll.use_pll,+ pllsysclk: main_pll.pllsysclk,+ pll48clk: main_pll.pll48clk,+ i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),+ sai: sai_clocks.real(real_sai_clk, self.i2s_ckin),+ }+ }++ #[cfg(any(feature = "stm32f411", feature = "stm32f412", feature = "stm32f446"))]+ #[inline(always)]+ fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {+ let i2s_clocks = self.i2s_clocks();+ #[cfg(feature = "stm32f446")]+ let sai_clocks = self.sai_clocks();++ // All PLLs are completely independent.+ let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);+ let i2s_pll = I2sPll::setup(pllsrcclk, i2s_clocks.pll_i2s_clk);+ #[cfg(feature = "stm32f446")]+ let sai_pll = SaiPll::setup(pllsrcclk, sai_clocks.pll_sai_clk);++ PllSetup {+ use_pll: main_pll.use_pll,+ use_i2spll: i2s_pll.use_pll,+ #[cfg(feature = "stm32f446")]+ use_saipll: sai_pll.use_pll,+ pllsysclk: main_pll.pllsysclk,+ pll48clk: main_pll.pll48clk,+ i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),+ #[cfg(feature = "stm32f446")]+ sai: sai_clocks.real(sai_pll.sai_clk, self.i2s_ckin),+ }+ }++ #[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ #[inline(always)]+ fn pll_setup(&self, pllsrcclk: u32, pllsysclk: Option<u32>) -> PllSetup {+ let i2s_clocks = self.i2s_clocks();+ #[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ let sai_clocks = self.sai_clocks();++ // We have separate PLLs, but they share the "M" divider.+ let main_pll = MainPll::fast_setup(pllsrcclk, self.hse.is_some(), pllsysclk, self.pll48clk);+ let i2s_pll = I2sPll::setup_shared_m(pllsrcclk, main_pll.m, i2s_clocks.pll_i2s_clk);+ #[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ let sai_pll =+ SaiPll::setup_shared_m(pllsrcclk, main_pll.m.or(i2s_pll.m), sai_clocks.pll_sai_clk);++ PllSetup {+ use_pll: main_pll.use_pll,+ use_i2spll: i2s_pll.use_pll,+ #[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ use_saipll: sai_pll.use_pll,+ pllsysclk: main_pll.pllsysclk,+ pll48clk: main_pll.pll48clk,+ i2s: i2s_clocks.real(i2s_pll.plli2sclk, self.i2s_ckin),+ #[cfg(any(+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ sai: sai_clocks.real(sai_pll.sai_clk, self.i2s_ckin),+ }+ }++ #[cfg(any(+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479",+ ))]+ fn sai_clocks(&self) -> SaiClocks {+ let sai1_ext = self.sai1_clk.is_some() && self.sai1_clk == self.i2s_ckin;+ #[cfg(not(feature = "stm32f446"))]+ let sai2_ext = self.sai2_clk.is_some() && self.sai2_clk == self.i2s_ckin;+ // Not the PLL output, but the target clock after the divider.+ let pll_sai_clk = if sai1_ext { None } else { self.sai1_clk };+ // The STM32F446 only supports I2S_CKIN for SAI1.+ #[cfg(feature = "stm32f446")]+ let pll_sai_clk2 = self.sai2_clk;+ #[cfg(not(feature = "stm32f446"))]+ let pll_sai_clk2 = if sai2_ext { None } else { self.sai2_clk };+ if pll_sai_clk.is_some() && pll_sai_clk2.is_some() && pll_sai_clk != pll_sai_clk2 {+ panic!("only one SAI PLL frequency implemented");+ }+ SaiClocks {+ sai1_ext,+ #[cfg(not(feature = "stm32f446"))]+ sai2_ext,+ pll_sai_clk,+ }+ }++ #[cfg(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ ))]+ fn i2s_clocks(&self) -> I2sClocks {+ let i2s_apb1_ext = self.i2s_apb1_clk.is_some() && self.i2s_apb1_clk == self.i2s_ckin;+ let i2s_apb2_ext = self.i2s_apb2_clk.is_some() && self.i2s_apb2_clk == self.i2s_ckin;+ let pll_i2s_clk = if i2s_apb1_ext {+ None+ } else {+ self.i2s_apb1_clk+ };+ let pll_i2s_clk2 = if i2s_apb2_ext {+ None+ } else {+ self.i2s_apb2_clk+ };+ if pll_i2s_clk.is_some() && pll_i2s_clk2.is_some() && pll_i2s_clk != pll_i2s_clk2 {+ panic!("only one I2S PLL frequency implemented");+ }+ I2sClocks {+ i2s_apb1_ext,+ i2s_apb2_ext,+ pll_i2s_clk,+ }+ }++ #[cfg(not(any(+ feature = "stm32f412",+ feature = "stm32f413",+ feature = "stm32f423",+ feature = "stm32f446",+ )))]+ fn i2s_clocks(&self) -> I2sClocks {+ let i2s_ext = self.i2s_clk.is_some() && self.i2s_clk == self.i2s_ckin;+ let pll_i2s_clk = if i2s_ext { None } else { self.i2s_clk };+ I2sClocks {+ i2s_ext,+ pll_i2s_clk,+ }+ }++ fn flash_setup(sysclk: u32) {+ use crate::stm32::FLASH;++ #[cfg(any(+ feature = "stm32f401",+ feature = "stm32f405",+ feature = "stm32f407",+ feature = "stm32f410",+ feature = "stm32f411",+ feature = "stm32f412",+ feature = "stm32f415",+ feature = "stm32f417",+ feature = "stm32f427",+ feature = "stm32f429",+ feature = "stm32f437",+ feature = "stm32f439",+ feature = "stm32f446",+ feature = "stm32f469",+ feature = "stm32f479"+ ))]+ let flash_latency_step = 30_000_000;++ #[cfg(any(feature = "stm32f413", feature = "stm32f423"))]+ let flash_latency_step = 25_000_000;++ unsafe {+ let flash = &(*FLASH::ptr());+ // Adjust flash wait states+ flash.acr.modify(|_, w| {+ w.latency().bits(((sysclk - 1) / flash_latency_step) as u8);+ w.prften().set_bit();+ w.icen().set_bit();+ w.dcen().set_bit()+ })+ }+ }++ /// Initialises the hardware according to CFGR state returning a Clocks instance.+ /// Panics if overclocking is attempted.+ pub fn freeze(self) -> Clocks {+ self.freeze_internal(false)+ }++ /// Initialises the hardware according to CFGR state returning a Clocks instance.+ /// Allows overclocking.+ pub unsafe fn freeze_unchecked(self) -> Clocks {+ self.freeze_internal(true)+ }++ pub fn freeze_internal(self, unchecked: bool) -> Clocks {
I do not see why it should be, but it was already pub before I started.
comment created time in 3 days
Pull request review commentstm32-rs/stm32f4xx-hal
features = ["stm32f429", "rt", "usb_fs"] targets = ["thumbv7em-none-eabihf"] [dependencies]+bxcan = ">=0.3.0"
bxcan = { version = "0.3.0", optional = true }
and then below "has-can = ["bxcan"]" to make bxcan optional?
comment created time in 3 days
pull request commentstm32-rs/stm32-rs
Correct IWDG and WWDG peripherals for the g4 family
diseralucacomment created time in 3 days
issue commentrust-embedded/embedded-hal
Shared type definitions (e.g. MHz, bps...)
@eldruin OK, I submitted a PR for integrating embedded-time for the stm32f3xx-hal device crate.
It was a pretty smooth integration for the most part except for the CountDown
/Periodic
timers due to the limitations on their generic constraint Into<Self::Time>
.
I want to see if there are some other devices crates that would be willing to accept a PR for this.
comment created time in 3 days
issue closedstm32-rs/stm32h7xx-hal
Hello, I'm trying to get a grasp of the paradigms of this library. I know this is probably a trivial question, but I'm not sure how to tackle it.
Essentially I have this:
fn main() -> ! {
...
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
// pass ccdr.clocks & ccdr.peripheral because we are unable to pass ccdr as its been moved for gpiob init
drivers::oled::init(
dp.TIM2,
&ccdr.clocks,
&ccdr.peripheral,
gpiob.pb6,
gpiob.pb7,
dp.I2C1,
);
}
But because peripheralREC
is defined within a macro, I cannot declare this as an input parameter type for my oled::init
function.
If peripheralREC
cannot be passed, then it requires me to restructure the initialization method where I would initialize the I2C
and TIM
peripherals (which is what drives the oled display) in the main function and then pass this to oled::init
which kind of breaks the encapsulation that I was intending for this.
What am I missing?
Kind regards
closed time in 3 days
ostenningissue commentstm32-rs/stm32h7xx-hal
The types you want to use for REC arguments are here: https://docs.rs/stm32h7xx-hal/0.8.0/stm32h7xx_hal/rcc/rec/index.html#structs
I encapsulate functionality like this:
use stm32h7xx_hal::{
gpio::*,
hal::digital::v2::OutputPin,
nb, pac,
prelude::*,
rcc::{self, rec},
serial,
};
pub struct Gps {
_tx: serial::Tx<pac::UART7>,
rx: serial::Rx<pac::UART7>,
reset: gpiog::PG1<Output<OpenDrain>>,
_int: gpiog::PG0<Input<Floating>>,
buffer: ArrayVec<[u8; 128]>,
}
impl Gps {
pub fn new(
tx: gpioe::PE8<Analog>,
rx: gpioe::PE7<Analog>,
uart: pac::UART7,
uart_rec: rec::Uart7,
reset: gpiog::PG1<Analog>,
int: gpiog::PG0<Analog>,
clocks: &rcc::CoreClocks,
) -> Self {
let tx = tx.into_alternate_af7();
let rx = rx.into_alternate_af7();
let mut uart = uart.serial((tx, rx), 9600.bps(), uart_rec, clocks).unwrap();
uart.listen(serial::Event::Rxne);
let (_tx, rx) = uart.split();
let mut reset = reset.into_open_drain_output();
reset.set_high().unwrap();
let _int = int.into_floating_input();
Self {
_tx,
rx,
reset,
_int,
buffer: ArrayVec::new(),
}
}
And then create like this:
let clocks = ccdr.clocks;
let prec = ccdr.peripheral;
let mut gps = gps::Gps::new(
gpioe.pe8, gpioe.pe7, dp.UART7, prec.UART7, gpiog.pg1, gpiog.pg0, &clocks,
);
comment created time in 4 days
pull request commentstm32-rs/stm32f4xx-hal
This works. Tested with Weekday set to 7, and date set to 2021-01-10, correctly rolled to 2021-01-11 and weekday of 1.
comment created time in 4 days
pull request commentstm32-rs/stm32f4xx-hal
I'm double checking this now, but I think this is good at this point. I'll mark it ready for review when I think that is the case.
comment created time in 4 days
issue openedstm32-rs/stm32h7xx-hal
Hello, I'm trying to get a grasp of the paradigms of this library. I know this is probably a trivial question, but I'm not sure how to tackle it.
Essentially I have this:
fn main() -> ! {
...
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
// pass ccdr.clocks & ccdr.peripheral because we are unable to pass ccdr as its been moved for gpiob init
drivers::oled::init(
dp.TIM2,
&ccdr.clocks,
&ccdr.peripheral,
gpiob.pb6,
gpiob.pb7,
dp.I2C1,
);
}
But because peripheralREC
is defined within a macro, I cannot declare this as an input parameter type for my oled::init
function.
If peripheralREC
cannot be passed, then it requires me to restructure the initialization method where I would initialize the I2C
interface (which is what drives the oled display) in the main function and then pass this to oled::init
which kind of breaks the encapsulation that I was intending for this.
What am I missing?
Kind regards
created time in 4 days
PR closed stm32-rs/stm32-rs
This PR moves the generic alt function definition from gpio_v2_common.yaml to gpio_v2_common_altfuncs.yaml. Chips that don't have detailed alt function definitions can import this new file, while those that do can instead import the file that defines them. In this case the F303 series imports gpio_v2_f303.yaml.
pr closed time in 4 days
pull request commentstm32-rs/stm32-rs
Add detailed alternate function names to STM32F303
Past9comment created time in 4 days
pull request commentstm32-rs/stm32-rs
Add detailed alternate function names to STM32F303
Past9comment created time in 4 days