profile
viewpoint
Malloc Voidstar AlyoshaVasilieva USA They/them

AlyoshaVasilieva/at-commands 0

Rust project for building and parsing at commands

AlyoshaVasilieva/crc-any 0

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

AlyoshaVasilieva/imxrt-rs 0

Rust for NXP i.MX RT

AlyoshaVasilieva/lolcate-rs 0

Lolcate -- A comically fast way of indexing and querying your filesystem. Replaces locate / mlocate / updatedb. Written in Rust.

AlyoshaVasilieva/mh-z19-rs 0

Winsen Infrared CO2 Module MH-Z19 serial "api" implementation in Rust.

AlyoshaVasilieva/probe-rs 0

A debugging toolset and library for debugging embedded ARM and RISC-V targets on a separate host

AlyoshaVasilieva/probe-run 0

Run embedded programs just like native ones

AlyoshaVasilieva/stm32-rs 0

Embedded Rust device crates for STM32 microcontrollers

PR opened stm32-rs/stm32f4xx-hal

wip reduce macros on serial
+374 -325

0 comment

1 changed file

pr created time in 15 hours

pull request commentstm32-rs/stm32f4xx-hal

Add rtc support

@therealprof What else is needed from me at this point?

mdrobnak

comment created time in a day

pull request commentstm32-rs/stm32-rs

Fix RCC SWS doc typo

AlyoshaVasilieva

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!

richardeoin

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

nordmoen

comment created time in a day

PR opened stm32-rs/stm32-rs

Rename SP3EN to SPI3EN for G4 Family

Closes #480.

Modifies SP3EN to SPI3EN for APB1ENR1 register for the G4 Family.

+3 -0

0 comment

1 changed file

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

richardeoin

comment created time in 2 days

push eventstm32-rs/stm32h7xx-hal

Richard Meadows

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

view details

Richard Meadows

commit sha 2809fefadaa36c13bc2264548e7ca263873aa014

Add allow for clippy type_complexity with 5th type parameter

view details

Richard Meadows

commit sha 1ac12e10f3f32393eca35c95e8bb9809038fe6f9

Merge pull request #178 from richardeoin/dma-const-buf1 Implement DMA for constant source buffers

view details

push time in 2 days

PR merged stm32-rs/stm32h7xx-hal

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.

+340 -297

1 comment

6 changed files

richardeoin

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

richardeoin

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

add can support

+//! # 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())

xoviat

comment created time in 3 days

Pull request review commentstm32-rs/stm32f4xx-hal

add can support

+//! # 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).

xoviat

comment created time in 3 days

Pull request review commentstm32-rs/stm32f4xx-hal

add can support

+//! # 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.

xoviat

comment created time in 3 days

pull request commentstm32-rs/stm32f4xx-hal

add can support

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.

xoviat

comment created time in 3 days

pull request commentstm32-rs/stm32f4xx-hal

rcc: I2S and SAI clocks

Apparently I messed up and caused some warnings about unused fields on F410/413/423. I will create a follow-up PR for those.

mgottschlag

comment created time in 3 days

Pull request review commentstm32-rs/stm32f4xx-hal

rcc: I2S and SAI clocks

+//! 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.

mgottschlag

comment created time in 3 days

Pull request review commentstm32-rs/stm32f4xx-hal

add can support

 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?

xoviat

comment 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.

nordmoen

comment created time in 3 days

issue closedstm32-rs/stm32h7xx-hal

Intended structure query

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

ostenning

issue commentstm32-rs/stm32h7xx-hal

Intended structure query

Ah, thank you so much.

ostenning

comment created time in 3 days

issue commentstm32-rs/stm32h7xx-hal

Intended structure query

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,
        );
ostenning

comment created time in 4 days

pull request commentstm32-rs/stm32f4xx-hal

Add rtc support

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.

mdrobnak

comment created time in 4 days

pull request commentstm32-rs/stm32f4xx-hal

Add rtc support

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.

mdrobnak

comment created time in 4 days

issue openedstm32-rs/stm32h7xx-hal

Intended structure query

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

Add detailed alternate function names to STM32F303

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.

+1714 -20

5 comments

6 changed files

Past9

pr closed time in 4 days

more