diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c50f925b..3bdeeaf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,15 @@ jobs: - stm32f446 - stm32f469 - stm32f479 + - stm32f722 + - stm32f723 + - stm32f730 + - stm32f745 + - stm32f746 + - stm32f765 + - stm32f767 + - stm32f769 + rust: - stable features: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3defa221..d7ce8be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] + - Integrate STM32F7 support - Implement `Ptr`, `Sealed`, `Steal` for generic `Periph` [#834] + - Use `&mut RCC` for `PER::enable/reset` - Unmacro `Adc` [#832] - Use `write` instead of `modify` to clear flags [#829] - Bump `stm32f4-staging` to 0.18, update other dependencies [#831] @@ -15,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - FMPI2c APB timings [#770] - Fefactor FMPI2c `embedded-hal` implementations [#784] +[#667]: https://github.com/stm32-rs/stm32f4xx-hal/pull/667 [#770]: https://github.com/stm32-rs/stm32f4xx-hal/pull/770 [#784]: https://github.com/stm32-rs/stm32f4xx-hal/pull/784 [#829]: https://github.com/stm32-rs/stm32f4xx-hal/pull/829 diff --git a/Cargo.toml b/Cargo.toml index d8ba37ba..3b6a0691 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,8 +67,15 @@ micromath = { version = "2.1.0", optional = true } [dependencies.stm32f4] package = "stm32f4-staging" -version = "0.19.0" +version = "0.20" features = ["atomics"] +optional = true + +[dependencies.stm32f7] +package = "stm32f7-staging" +version = "0.18.1" +features = ["atomics"] +optional = true [dependencies.time] version = "0.3.37" @@ -93,7 +100,7 @@ version = "0.5.0" optional = true [dev-dependencies] -defmt = "0.3.4" +defmt = "1.0" defmt-rtt = "0.4.0" panic-probe = { version = "0.3.2", features = ["print-defmt"] } panic-semihosting = "0.6.0" @@ -127,6 +134,11 @@ default-features = false features = ["macros"] [features] +f4 = ["dep:stm32f4", "bb", "dma", "i2c_v1", "spi_v1", "uart_v2"] +f7 = ["dep:stm32f7", "dep:micromath", "dma", "i2c_v2", "spi_v2", "uart_v3"] + +# F4 + #! Use one of the supported STM32-serie related features: #! `stm32f401`, `stm32f405`, `stm32f407`, `stm32f415`, `stm32f417`, `stm32f410`, #! `stm32f411`, `stm32f412`, `stm32f413`, `stm32f423`, `stm32f427`, `stm32f429`, @@ -134,32 +146,56 @@ features = ["macros"] # Note: stm32f4 has only one feature for some very similar device families, # so it's intended for e.g. stm32f405/415 to both enable stm32f4/stm32f405. -stm32f401 = ["stm32f4/stm32f401", "gpio-f401"] -stm32f405 = ["stm32f4/stm32f405", "gpio-f417"] -stm32f407 = ["stm32f4/stm32f407", "gpio-f417"] -stm32f415 = ["stm32f4/stm32f405", "gpio-f417", "cryp"] -stm32f417 = ["stm32f4/stm32f407", "gpio-f417", "cryp"] -stm32f410 = ["stm32f4/stm32f410", "gpio-f410"] -stm32f411 = ["stm32f4/stm32f411", "gpio-f411"] -stm32f412 = ["stm32f4/stm32f412", "gpio-f412"] -stm32f413 = ["stm32f4/stm32f413", "gpio-f413"] -stm32f423 = ["stm32f4/stm32f413", "gpio-f413", "aes"] -stm32f427 = ["stm32f4/stm32f427", "gpio-f427", "fsmc"] -stm32f429 = ["stm32f4/stm32f429", "gpio-f427", "fmc", "ltdc"] -stm32f437 = ["stm32f4/stm32f427", "gpio-f427", "fsmc", "cryp"] -stm32f439 = ["stm32f4/stm32f429", "gpio-f427", "fmc", "cryp", "ltdc"] -stm32f446 = ["stm32f4/stm32f446", "gpio-f446"] -stm32f469 = ["stm32f4/stm32f469", "gpio-f469"] -stm32f479 = ["stm32f4/stm32f469", "gpio-f469", "cryp"] +stm32f401 = ["svd-f401"] +stm32f405 = ["svd-f405"] +stm32f407 = ["svd-f407"] +stm32f415 = ["svd-f405", "cryp"] +stm32f417 = ["svd-f407", "cryp"] +stm32f410 = ["svd-f410"] +stm32f411 = ["svd-f411"] +stm32f412 = ["svd-f412"] +stm32f413 = ["svd-f413"] +stm32f423 = ["svd-f413", "aes"] +stm32f427 = ["svd-f427"] +stm32f429 = ["svd-f429"] +stm32f437 = ["svd-f427", "cryp"] +stm32f439 = ["svd-f429", "cryp"] +stm32f446 = ["svd-f446"] +stm32f469 = ["svd-f469"] +stm32f479 = ["svd-f469", "cryp"] + +svd-f401 = ["f4", "stm32f4?/stm32f401", "gpio-f401"] +svd-f405 = ["f4", "stm32f4?/stm32f405", "gpio-f417"] +svd-f407 = ["f4", "stm32f4?/stm32f407", "gpio-f417", "eth"] +svd-f410 = ["f4", "stm32f4?/stm32f410", "gpio-f410"] +svd-f411 = ["f4", "stm32f4?/stm32f411", "gpio-f411"] +svd-f412 = ["f4", "stm32f4?/stm32f412", "gpio-f412"] +svd-f413 = ["f4", "stm32f4?/stm32f413", "gpio-f413"] +svd-f427 = ["f4", "stm32f4?/stm32f427", "gpio-f427", "fsmc"] +svd-f429 = ["f4", "stm32f4?/stm32f429", "gpio-f427", "fmc", "ltdc"] +svd-f446 = ["f4", "stm32f4?/stm32f446", "gpio-f446"] +svd-f469 = ["f4", "stm32f4?/stm32f469", "gpio-f469"] gpio-f401 = [ + "gpioc", "gpiod", "gpioe", + "gpioh", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s2ext", + "i2s3", + "i2s3ext", + "rtc", "otg-fs", "sdio", + "spi1", + "spi2", "spi3", "spi4", + "sys", "tim1", "tim2", "tim3", @@ -168,25 +204,58 @@ gpio-f401 = [ "tim9", "tim10", "tim11", + "usart1", + "usart2", + "usart6", "rcc_shared_m", ] gpio-f410 = [ + "gpioc", + "gpioh", "dac", "fmpi2c1", + "i2c2", + "i2s", + "i2s1", + "i2s2", + "i2s5", "lptim1", + "rtc", + "spi1", + "spi2", "spi5", + "sys", "tim1", "tim5", "tim6", "tim9", "tim11", + "usart1", + "usart2", + "usart6", ] gpio-f411 = [ + "gpioc", "gpiod", "gpioe", # "gpioi", + "gpioh", + "i2c2", "i2c3", "otg-fs", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", + "rtc", "sdio", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "sys", "tim1", "tim2", "tim3", @@ -195,28 +264,41 @@ gpio-f411 = [ "tim9", "tim10", "tim11", - "spi3", - "spi4", - "spi5", + "usart1", + "usart2", + "usart6", ] gpio-f412 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "can1", "can2", "dfsdm1", "fmpi2c1", "fsmc", + "i2c2", "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", "quadspi", "otg-fs", "rng", + "rtc", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", + "sys", "tim1", "tim2", "tim3", @@ -231,14 +313,19 @@ gpio-f412 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "rcc_i2s_apb", ] gpio-f413 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "can1", "can2", "can3", @@ -247,16 +334,27 @@ gpio-f413 = [ "dfsdm2", "fsmc", "fmpi2c1", + "i2c2", "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", "lptim1", "quadspi", "otg-fs", "rng", + "rtc", "sai1", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", + "sys", "tim1", "tim2", "tim3", @@ -271,7 +369,10 @@ gpio-f413 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "uart4", "uart5", "uart7", @@ -281,25 +382,34 @@ gpio-f413 = [ "rcc_i2s_apb", ] gpio-f417 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioi", + "gpioh", "adc2", "adc3", "can1", "can2", "dac", "dcmi", - "eth", "fsmc", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s3", "otg-fs", "otg-hs", "rng", + "rtc", "sdio", + "spi1", + "spi2", "spi3", + "sys", "tim1", "tim2", "tim3", @@ -314,16 +424,21 @@ gpio-f417 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "uart4", "uart5", "rcc_shared_m", ] gpio-f427 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "gpioi", "gpioj", "gpiok", @@ -335,16 +450,24 @@ gpio-f427 = [ "dcmi", "dma2d", "eth", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s3", "otg-fs", "otg-hs", "rng", + "rtc", "sai1", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", "spi6", + "sys", "tim1", "tim2", "tim3", @@ -359,7 +482,10 @@ gpio-f427 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "uart4", "uart5", "uart7", @@ -367,28 +493,40 @@ gpio-f427 = [ "rcc_shared_m", ] gpio-f446 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "adc2", "adc3", "can1", "can2", "dac", "dcmi", + "fmc", "fmpi2c1", "fmc", + "i2c2", "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", "quadspi", + "rtc", "otg-fs", "otg-hs", "sai1", "sai2", "sdio", + "spdifrx", + "spi1", + "spi2", "spi3", "spi4", - "spdifrx", + "sys", "tim1", "tim2", "tim3", @@ -403,16 +541,21 @@ gpio-f446 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "uart4", "uart5", "rcc_i2s_apb", ] gpio-f469 = [ + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "gpioi", "gpioj", "gpiok", @@ -426,18 +569,26 @@ gpio-f469 = [ "dsihost", "eth", "fmc", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s3", "ltdc", "quadspi", "otg-fs", "otg-hs", "rng", + "rtc", "sai1", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", "spi6", + "sys", "tim1", "tim2", "tim3", @@ -452,7 +603,10 @@ gpio-f469 = [ "tim12", "tim13", "tim14", + "usart1", + "usart2", "usart3", + "usart6", "uart4", "uart5", "uart7", @@ -460,6 +614,287 @@ gpio-f469 = [ "rcc_shared_m", ] +# F7 + +stm32f722 = ["svd-f722"] +stm32f723 = ["svd-f723"] +stm32f730 = ["svd-f730"] +stm32f732 = ["svd-f732"] +stm32f733 = ["svd-f733"] +stm32f745 = ["svd-f745"] +stm32f746 = ["svd-f746"] +stm32f750 = ["svd-f750"] +stm32f756 = ["svd-f756"] +stm32f765 = ["svd-f765"] +stm32f767 = ["svd-f767"] +stm32f769 = ["svd-f769"] +stm32f777 = ["svd-f777"] +stm32f778 = ["svd-f778"] +stm32f779 = ["svd-f779"] + +svd-f722 = ["f7", "stm32f7?/stm32f722", "gpio-f72x"] +svd-f723 = ["f7", "stm32f7?/stm32f723", "gpio-f72x", "usb_hs_phy"] +svd-f732 = ["f7", "stm32f7?/stm32f732", "gpio-f72x"] +svd-f733 = ["f7", "stm32f7?/stm32f733", "gpio-f72x", "usb_hs_phy"] +svd-f730 = ["f7", "stm32f7?/stm32f730", "gpio-f72x", "aes", "usb_hs_phy"] +svd-f745 = ["f7", "stm32f7?/stm32f745", "gpio-f746"] +svd-f746 = ["f7", "stm32f7?/stm32f746", "gpio-f746"] +svd-f750 = ["f7", "stm32f7?/stm32f750", "gpio-f746"] +svd-f756 = ["f7", "stm32f7?/stm32f756", "gpio-f746"] +svd-f765 = ["f7", "stm32f7?/stm32f765", "gpio-f76x"] +svd-f767 = [ + "f7", + "stm32f7?/stm32f767", + "gpio-f76x", + "dsihost", + "can3", + "jpeg", + "mdios", + "sdmmc2", +] +svd-f769 = [ + "f7", + "stm32f7?/stm32f769", + "gpio-f76x", + "dfsdm1", + "dsihost", + "can3", + "jpeg", + "mdios", + "sdmmc2", +] +svd-f777 = [ + "f7", + "stm32f7?/stm32f777", + "gpio-f76x", + "dsihost", + "can3", + "jpeg", + "mdios", + "sdmmc2", +] +svd-f778 = [ + "f7", + "stm32f7?/stm32f778", + "gpio-f76x", + "dsihost", + "can3", + "jpeg", + "mdios", + "sdmmc2", +] +svd-f779 = [ + "f7", + "stm32f7?/stm32f779", + "gpio-f76x", + "dfsdm1", + "dsihost", + "can3", + "jpeg", + "mdios", + "sdmmc2", +] + +gpio-f72x = [ + "adc2", + "adc3", + "can1", + "dac", + "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "i2c2", + "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", + "quadspi", + "rng", + "rtc", + "sai1", + "sai2", + "sdmmc1", + "sdmmc2", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim6", + "tim7", + "tim8", + "tim9", + "uart4", + "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", +] +gpio-f746 = [ + "adc2", + "adc3", + "dac", + "dma2d", + "can1", + "can2", + "cec", + "cryp", + "dcmi", + "eth", + "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "gpioj", + "gpiok", + "hash", + "i2c2", + "i2c3", + "i2c4", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", + "ltdc", + "quadspi", + "rng", + "rtc", + "sai1", + "sai2", + "sdmmc1", + "spdifrx", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "spi6", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim6", + "tim7", + "tim8", + "tim9", + "uart4", + "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", +] +gpio-f76x = [ + "adc2", + "adc3", + "dac", + "dma2d", + "can1", + "can2", + "cec", + "cryp", + "dcmi", + "eth", + "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "gpioj", + "gpiok", + "hash", + "i2c2", + "i2c3", + "i2c4", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", + "ltdc", + "quadspi", + "rng", + "rtc", + "sai1", + "sai2", + "sdmmc1", + "spdifrx", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "spi6", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim6", + "tim7", + "tim8", + "tim9", + "uart4", + "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", +] + + ## Support monotonic timers and other stuff that can be used by [RTICv1 framework](https://crates.io/crates/cortex-m-rtic) rtic1 = ["dep:rtic-monotonic", "dep:systick-monotonic", "cortex-m-rtic"] @@ -478,7 +913,13 @@ rtic-tim4 = [] rtic-tim5 = [] ## Implementation of `defmt::Format` for public enums and structures. See [defmt](https://crates.io/crates/defmt) -defmt = ["dep:defmt", "stm32f4/defmt", "fugit/defmt", "nb/defmt-0-3"] +defmt = [ + "dep:defmt", + "stm32f4?/defmt", + "stm32f7?/defmt", + "fugit/defmt", + "nb/defmt-0-3", +] ## bxCAN peripheral support. See [bxcan](https://crates.io/crates/bxcan) can = ["dep:bxcan"] @@ -499,6 +940,15 @@ sdio-host = ["dep:sdio-host"] # Next features are for internal use only!!! +bb = [] +dma = [] +i2c_v1 = [] +i2c_v2 = [] +spi_v1 = [] +spi_v2 = [] +uart_v2 = [] +uart_v3 = [] +usb_hs_phy = [] dfsdm = [] sai = [] rcc_shared_m = [] @@ -506,43 +956,102 @@ rcc_i2s_apb = [] adc2 = [] adc3 = [] +adf1 = [] aes = [] can1 = [] can2 = [] can3 = [] +cec = [] cryp = [] +cm4 = [] +crs1 = [] +comp1 = [] +comp2 = [] +comp3 = [] +comp4 = [] +comp5 = [] +comp6 = [] +comp7 = [] +crs = [] dac = [] dcmi = [] +debug = [] dfsdm1 = ["dfsdm"] dfsdm2 = ["dfsdm"] dma2d = [] dsihost = ["embedded-display-controller"] +hash = [] eth = [] +fdcan1 = [] +fdcan2 = [] +fdcan3 = [] fmc = [] fsmc = [] fmpi2c1 = ["dep:micromath"] +gpioc = [] gpiod = [] gpioe = [] gpiof = [] gpiog = [] +gpioh = [] gpioi = [] gpioj = [] gpiok = [] +hdmi = [] +hrtim1 = [] +hspi1 = [] +i2c2 = [] i2c3 = [] +i2c4 = [] +i2c5 = [] +i2c6 = [] +i2s1 = [] +i2s2 = [] +i2s2ext = [] +i2s3 = [] +i2s3ext = [] +i2s4 = [] +i2s5 = [] +i2s6 = [] +ir = [] +jpeg = [] +lcd = [] lptim1 = [] +lptim2 = [] +lptim3 = [] +lptim4 = [] +lptim5 = [] +lpuart1 = [] +lpuart2 = [] ltdc = ["dep:micromath"] +mdios = [] +mdf1 = [] quadspi = [] +octospi = [] +opamp2 = [] otg-fs = [] otg-hs = [] +pssi = [] +pwr = [] +rf = [] rng = [] +rtc = [] sai1 = ["sai"] sai2 = ["sai"] +sai3 = [] +sai4 = [] sdio = [] +sdmmc1 = [] +sdmmc2 = [] +spi1 = [] +spi2 = [] spi3 = [] spi4 = [] spi5 = [] spi6 = [] +sys = [] spdifrx = [] +swpmi1 = [] tim1 = [] tim2 = [] tim3 = [] @@ -557,13 +1066,39 @@ tim11 = [] tim12 = [] tim13 = [] tim14 = [] +tim15 = [] +tim16 = [] +tim17 = [] +tim19 = [] +tim20 = [] +tim21 = [] +tim22 = [] +tim23 = [] +tim24 = [] +timx = [] +ts = [] +tsc = [] +ucpd1 = [] +ucpd2 = [] +usart1 = [] +usart2 = [] usart3 = [] +usart4 = [] +usart5 = [] +usart6 = [] +usart7 = [] +usart8 = [] +usart10 = [] uart4 = [] uart5 = [] uart7 = [] uart8 = [] uart9 = [] uart10 = [] +usb = [] # "dep:stm32-usbd" +v_ref = [] + +disabled = [] [profile.dev] debug = true @@ -578,7 +1113,7 @@ opt-level = "s" [[example]] name = "analog-stopwatch-with-spi-ssd1306" -required-features = ["spi4", "tim2", "gpioe", "gpiog"] # stm32f429 +required-features = ["f4", "spi4", "tim2", "gpioe", "gpiog"] # stm32f429 [[example]] name = "blinky-timer-irq" @@ -661,7 +1196,7 @@ required-features = ["rng"] # stm32f407 [[example]] name = "rtc" -required-features = [] +required-features = ["f4"] [[example]] name = "rtc_alarm" @@ -669,7 +1204,7 @@ required-features = ["stm32f411"] [[example]] name = "rtic-adc-dma" -required-features = ["rtic1"] # stm32f401 +required-features = ["rtic1", "f4"] # stm32f401 [[example]] name = "rtic-button" @@ -739,6 +1274,10 @@ required-features = ["stm32f411"] name = "uart-dma" required-features = ["stm32f405"] +[[example]] +name = "spi_16" +required-features = ["gpiod"] + [[example]] name = "ssd1306-image" required-features = [] # stm32f411 @@ -773,7 +1312,7 @@ required-features = ["otg-fs", "usb_fs"] # stm32f407 [[example]] name = "usb-serial-poll" -required-features = ["otg-fs", "usb_fs"] # stm32f401 +required-features = ["otg-fs", "usb_fs", "f4"] # stm32f401 [[example]] name = "ws2812-spi" diff --git a/README.md b/README.md index 9dcd2d11..551ee9a8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ stm32f4xx-hal [![Continuous integration](https://github.com/stm32-rs/stm32f4xx-hal/workflows/Continuous%20integration/badge.svg)](https://github.com/stm32-rs/stm32f4xx-hal) _stm32f4xx-hal_ contains a multi device hardware abstraction on top of the -peripheral access API for the STMicro STM32F4 series microcontrollers. The +peripheral access API for the STMicro STM32F4/F7 series microcontrollers. The selection of the MCU is done by feature gates, typically specified by board support crates. Currently supported configurations are: @@ -20,25 +20,44 @@ support crates. Currently supported configurations are: * stm32f401 * stm32f405 * stm32f407 + + * stm32f410 * stm32f411 * stm32f412 - - * stm32f413 * stm32f415 * stm32f417 * stm32f423 -* stm32f427 -* stm32f429 +* stm32f427 +* stm32f429 * stm32f437 * stm32f439 * stm32f446 * stm32f469 * stm32f479 + + +* stm32f722 +* stm32f723 +* stm32f730 +* stm32f732 +* stm32f733 +* stm32f745 +* stm32f746 + + +* stm32f756 +* stm32f765 +* stm32f767 +* stm32f769 +* stm32f777 +* stm32f778 +* stm32f779 + The idea behind this crate is to gloss over the slight differences in the diff --git a/build.rs b/build.rs index 8e25570e..d09e1631 100644 --- a/build.rs +++ b/build.rs @@ -23,7 +23,9 @@ impl IteratorExt for T { fn main() { let _chip_name = match env::vars() .map(|(a, _)| a) - .filter(|x| x.starts_with("CARGO_FEATURE_STM32F4")) + .filter(|x| { + x.starts_with("CARGO_FEATURE_STM32F4") || x.starts_with("CARGO_FEATURE_STM32F7") + }) .get_one() { Ok(x) => x, diff --git a/examples/spi_16.rs b/examples/spi_16.rs new file mode 100644 index 00000000..fcd69979 --- /dev/null +++ b/examples/spi_16.rs @@ -0,0 +1,60 @@ +#![no_main] +#![no_std] + +use panic_semihosting as _; + +use stm32f4xx_hal as hal; + +use hal::{ + pac, + prelude::*, + spi::{NoMiso, Spi}, +}; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + let p = pac::Peripherals::take().unwrap(); + + let rcc = p.RCC.constrain(); + let clocks = rcc.cfgr.freeze(); + + let gpioa = p.GPIOA.split(); + let gpioc = p.GPIOC.split(); + let gpiod = p.GPIOD.split(); + + // Configure pin for button. This happens to be the pin for the USER button + // on the NUCLEO-F746ZG board. + let button = gpioc.pc13.into_floating_input(); + + // Prepare pins for SPI + let mut ncs = gpiod.pd14.into_push_pull_output(); + let sck = gpioa.pa5; + let mosi = gpioa.pa7; + + // Set NCS pin to high (disabled) initially + ncs.set_high(); + + // Initialize SPI + let mut spi = Spi::new( + p.SPI1, + (sck, NoMiso::new(), mosi), + embedded_hal::spi::MODE_0, + 250.kHz(), + &clocks, + ) + .frame_size_16bit(); + + // Use a button to control output via the Maxim Integrated MAX5214 DAC. + loop { + let data = if button.is_high() { 0xffff } else { 0x0000 }; + + let word: u16 = (0b01 << 14) | // write-through mode + (data & 0x3fff); // data bits + + ncs.set_low(); + spi.write(&[word]).unwrap(); + ncs.set_high(); + } +} diff --git a/src/adc.rs b/src/adc.rs index 25785fa9..5484f604 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -141,8 +141,13 @@ use core::fmt; use core::ops::Deref; pub mod config; + +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f7")] +mod f7; + /// Vref internal signal, used for calibration pub struct Vref; @@ -532,16 +537,15 @@ impl Adc { //Set the sample time for the channel let st = sample_time as u8; - let ch = channel as u8; match channel { 0..=9 => self .adc_reg .smpr2() - .modify(|_, w| unsafe { w.smp(ch).bits(st) }), + .modify(|_, w| unsafe { w.smp(channel).bits(st) }), 10..=18 => self .adc_reg .smpr1() - .modify(|_, w| unsafe { w.smp(ch - 10).bits(st) }), + .modify(|_, w| unsafe { w.smp(channel - 10).bits(st) }), _ => unimplemented!(), }; } diff --git a/src/adc/f7.rs b/src/adc/f7.rs new file mode 100644 index 00000000..53db7ca6 --- /dev/null +++ b/src/adc/f7.rs @@ -0,0 +1,63 @@ +use super::*; + +// See "Datasheet - production data" +// Pinouts and pin description (page 66..) +adc_pins!( + gpio::PA0 => (ADC1, 0), + gpio::PA1 => (ADC1, 1), + gpio::PA2 => (ADC1, 2), + gpio::PA3 => (ADC1, 3), + gpio::PA4 => (ADC1, 4), + gpio::PA5 => (ADC1, 5), + gpio::PA6 => (ADC1, 6), + gpio::PA7 => (ADC1, 7), + gpio::PB0 => (ADC1, 8), + gpio::PB1 => (ADC1, 9), + gpio::PC0 => (ADC1, 10), + gpio::PC1 => (ADC1, 11), + gpio::PC2 => (ADC1, 12), + gpio::PC3 => (ADC1, 13), + gpio::PC4 => (ADC1, 14), + gpio::PC5 => (ADC1, 15), + Temperature => (ADC1, 18), + Vbat => (ADC1, 18), + Vref => (ADC1, 17), +); + +adc_pins!( + gpio::PA0 => (ADC2, 0), + gpio::PA1 => (ADC2, 1), + gpio::PA2 => (ADC2, 2), + gpio::PA3 => (ADC2, 3), + gpio::PA4 => (ADC2, 4), + gpio::PA5 => (ADC2, 5), + gpio::PA6 => (ADC2, 6), + gpio::PA7 => (ADC2, 7), + gpio::PB0 => (ADC2, 8), + gpio::PB1 => (ADC2, 9), + gpio::PC0 => (ADC2, 10), + gpio::PC1 => (ADC2, 11), + gpio::PC2 => (ADC2, 12), + gpio::PC3 => (ADC2, 13), + gpio::PC4 => (ADC2, 14), + gpio::PC5 => (ADC2, 15), +); + +adc_pins!( + gpio::PA0 => (ADC3, 0), + gpio::PA1 => (ADC3, 1), + gpio::PA2 => (ADC3, 2), + gpio::PA3 => (ADC3, 3), + gpio::PF6 => (ADC3, 4), + gpio::PF7 => (ADC3, 5), + gpio::PF8 => (ADC3, 6), + gpio::PF9 => (ADC3, 7), + gpio::PF10 => (ADC3, 8), + gpio::PF3 => (ADC3, 9), + gpio::PC0 => (ADC3, 10), + gpio::PC1 => (ADC3, 11), + gpio::PC2 => (ADC3, 12), + gpio::PC3 => (ADC3, 13), + gpio::PF4 => (ADC3, 14), + gpio::PF5 => (ADC3, 15), +); diff --git a/src/dma/traits.rs b/src/dma/traits.rs index a6b461a7..3b040886 100644 --- a/src/dma/traits.rs +++ b/src/dma/traits.rs @@ -282,6 +282,7 @@ pub unsafe trait PeriAddress { } // Convenience macro for implementing addresses on peripherals +#[allow(unused)] macro_rules! address { ($(($peripheral:ty, $register:ident, $size: ty)),+ $(,)*) => { $( @@ -296,6 +297,7 @@ macro_rules! address { )+ }; } +#[allow(unused)] use address; /// Type alias to a DMA RegisterBlock. @@ -333,7 +335,17 @@ macro_rules! dma_map { } use dma_map; +#[cfg(feature = "f4")] mod f4; +#[allow(unused)] +#[cfg(feature = "f4")] +pub use f4::*; + +#[cfg(feature = "f7")] +mod f7; +#[allow(unused)] +#[cfg(feature = "f7")] +pub use f7::*; #[cfg(feature = "dfsdm")] pub struct FLT { diff --git a/src/dma/traits/f7.rs b/src/dma/traits/f7.rs new file mode 100644 index 00000000..de98a654 --- /dev/null +++ b/src/dma/traits/f7.rs @@ -0,0 +1,227 @@ +use super::*; + +dma_map! { + (Stream0:0, pac::SPI3, [PeripheralToMemory]), //SPI3_RX + (Stream2:0, pac::SPI3, [PeripheralToMemory]), //SPI3_RX + (Stream3:0, pac::SPI2, [PeripheralToMemory]), //SPI2_RX + (Stream4:0, pac::SPI2, [MemoryToPeripheral]), //SPI2_TX + (Stream5:0, pac::SPI3, [MemoryToPeripheral]), //SPI3_TX + (Stream7:0, pac::SPI3, [MemoryToPeripheral]), //SPI3_TX + + (Stream0:1, pac::I2C1, [PeripheralToMemory]), //I2C1_RX + (Stream1:1, pac::I2C3, [PeripheralToMemory]), //I2C3_RX + (Stream2:1, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM7_UP + (Stream4:1, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM7_UP + (Stream5:1, pac::I2C1, [PeripheralToMemory]), //I2C1_RX + (Stream6:1, pac::I2C1, [MemoryToPeripheral]), //I2C1_TX + (Stream7:1, pac::I2C1, [MemoryToPeripheral]), //I2C1_TX + + (Stream0:2, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM4_CH1 + (Stream3:2, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM4_CH2 + (Stream6:2, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM4_UP + (Stream7:2, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM4_CH3 + + (Stream1:3, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_CH3 + (Stream1:3, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_UP + (Stream2:3, pac::I2C3, [PeripheralToMemory]), //I2C3_RX + (Stream4:3, pac::I2C3, [MemoryToPeripheral]), //I2C3_TX + (Stream5:3, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_CH1 + (Stream6:3, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_CH2 + (Stream6:3, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_CH4 + (Stream7:3, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_CH4 + (Stream7:3, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM2_UP + + (Stream0:4, pac::UART5, [PeripheralToMemory]), //UART5_RX + (Stream1:4, pac::USART3, [PeripheralToMemory]), //USART3_RX + (Stream2:4, pac::UART4, [PeripheralToMemory]), //UART4_RX + (Stream3:4, pac::USART3, [MemoryToPeripheral]), //USART3_TX + (Stream4:4, pac::UART4, [MemoryToPeripheral]), //UART4_TX + (Stream5:4, pac::USART2, [PeripheralToMemory]), //USART2_RX + (Stream6:4, pac::USART2, [MemoryToPeripheral]), //USART2_TX + (Stream7:4, pac::UART5, [MemoryToPeripheral]), //UART5_TX + + (Stream0:5, pac::UART8, [MemoryToPeripheral]), //UART8_TX + (Stream1:5, pac::UART7, [MemoryToPeripheral]), //UART7_TX + (Stream2:5, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH4 + (Stream2:5, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_UP + (Stream3:5, pac::UART7, [PeripheralToMemory]), //UART7_RX + (Stream4:5, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH1 + (Stream4:5, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_TRIG + (Stream5:5, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH2 + (Stream6:5, pac::UART8, [PeripheralToMemory]), //UART8_RX + (Stream7:5, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH3 + + (Stream0:6, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH3 + (Stream0:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_UP + (Stream1:6, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH4 + (Stream1:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_TRIG + (Stream2:6, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH1 + (Stream3:6, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH4 + (Stream3:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_TRIG + (Stream4:6, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH2 + (Stream6:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_UP + + (Stream1:7, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM6_UP + (Stream2:7, pac::I2C2, [PeripheralToMemory]), //I2C2_RX + (Stream3:7, pac::I2C2, [PeripheralToMemory]), //I2C2_RX + (Stream4:7, pac::USART3, [MemoryToPeripheral]), //USART3_TX:DMA_CHANNEL_7 + (Stream5:7, pac::DAC, [MemoryToPeripheral]), //DAC1 + //(Stream6:7, pac::DAC2, [MemoryToPeripheral]), //DAC2 + (Stream7:7, pac::I2C2, [MemoryToPeripheral]), //I2C2_TX + + + (Stream0:0, pac::ADC1, [PeripheralToMemory]), //ADC1 + (Stream1:0, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_A + (Stream2:0, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH1 + (Stream2:0, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH2 + (Stream2:0, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH3 + (Stream3:0, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_A + (Stream4:0, pac::ADC1, [PeripheralToMemory]), //ADC1 + (Stream5:0, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_B:DMA_CHANNEL_0 + (Stream6:0, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH1 + (Stream6:0, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH2 + (Stream6:0, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH3 + (Stream7:0, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI2_B:DMA_CHANNEL_0 + + (Stream2:1, pac::ADC2, [PeripheralToMemory]), //ADC2 + (Stream3:1, pac::ADC2, [PeripheralToMemory]), //ADC2 + (Stream4:1, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_B + + (Stream0:2, pac::ADC3, [PeripheralToMemory]), //ADC3 + (Stream1:2, pac::ADC3, [PeripheralToMemory]), //ADC3 + (Stream3:2, pac::SPI5, [PeripheralToMemory]), //SPI5_RX + (Stream4:2, pac::SPI5, [MemoryToPeripheral]), //SPI5_TX + + (Stream0:3, pac::SPI1, [PeripheralToMemory]), //SPI1_RX + (Stream2:3, pac::SPI1, [PeripheralToMemory]), //SPI1_RX + (Stream3:3, pac::SPI1, [MemoryToPeripheral]), //SPI1_TX + (Stream4:3, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI2_A + (Stream5:3, pac::SPI1, [MemoryToPeripheral]), //SPI1_TX + (Stream6:3, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI2_B + (Stream7:3, pac::QUADSPI, [MemoryToPeripheral | PeripheralToMemory]), //QUADSPI + + (Stream0:4, pac::SPI4, [PeripheralToMemory]), //SPI4_RX + (Stream1:4, pac::SPI4, [MemoryToPeripheral]), //SPI4_TX + (Stream2:4, pac::USART1, [PeripheralToMemory]), //USART1_RX + (Stream3:4, pac::SDMMC1, [MemoryToPeripheral | PeripheralToMemory]), //SDMMC1 + (Stream5:4, pac::USART1, [PeripheralToMemory]), //USART1_RX + (Stream6:4, pac::SDMMC1, [MemoryToPeripheral | PeripheralToMemory]), //SDMMC1 + (Stream7:4, pac::USART1, [MemoryToPeripheral]), //USART1_TX + + (Stream1:5, pac::USART6, [PeripheralToMemory]), //USART6_RX + (Stream2:5, pac::USART6, [PeripheralToMemory]), //USART6_RX + (Stream3:5, pac::SPI4, [PeripheralToMemory]), //SPI4_RX:DMA_CHANNEL_5 + (Stream4:5, pac::SPI4, [MemoryToPeripheral]), //SPI4_TX:DMA_CHANNEL_5 + (Stream6:5, pac::USART6, [MemoryToPeripheral]), //USART6_TX + (Stream7:5, pac::USART6, [MemoryToPeripheral]), //USART6_TX + + (Stream0:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_TRIG + (Stream1:6, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH1 + (Stream2:6, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH2 + (Stream3:6, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH1 + (Stream4:6, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH4 + (Stream4:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_TRIG/COM + (Stream5:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_UP + (Stream6:6, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH3 + + (Stream1:7, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_UP + (Stream2:7, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH1 + (Stream3:7, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH2 + (Stream4:7, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH3 + (Stream5:7, pac::SPI5, [PeripheralToMemory]), //SPI5_RX:DMA_CHANNEL_7 + (Stream6:7, pac::SPI5, [MemoryToPeripheral]), //SPI5_TX:DMA_CHANNEL_7 + (Stream7:7, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH4 + (Stream7:7, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_COM/TRIG +} + +#[cfg(feature = "spdifrx")] +dma_map!( + (Stream1:0, pac::SPDIFRX, [PeripheralToMemory]), //SPDIF_RX_DT + //(Stream6:0, SPDIFRX_CS, [PeripheralToMemory]), //SPDIF_RX_CS +); + +#[cfg(feature = "i2c4")] +dma_map!( + (Stream2:2, pac::I2C4, [PeripheralToMemory]), //I2C4_RX + (Stream5:2, pac::I2C4, [PeripheralToMemory]), //I2C4_RX +); + +#[cfg(feature = "sdmmc2")] +dma_map!( + (Stream0:11, pac::SDMMC2, [MemoryToPeripheral | PeripheralToMemory]), //SDMMC2 + (Stream5:11, pac::SDMMC2, [MemoryToPeripheral | PeripheralToMemory]), //SDMMC2 +); + +#[cfg(feature = "dcmi")] +dma_map!( + (Stream1:1, pac::DCMI, [PeripheralToMemory]), //DCMI + (Stream7:1, pac::DCMI, [PeripheralToMemory]), //DCMI +); +#[cfg(feature = "dcmi")] +address!((pac::DCMI, dr, u32),); + +#[cfg(feature = "spi6")] +dma_map!( + (Stream5:1, pac::SPI6, [MemoryToPeripheral]), //SPI6_TX + (Stream6:1, pac::SPI6, [PeripheralToMemory]), //SPI6_RX +); + +#[cfg(feature = "spi6")] +address!((pac::SPI6, dr, u8),); + +#[cfg(feature = "aes")] +dma_map!( + (Stream6:2, AES_IN, [MemoryToPeripheral]), //AES_IN + (Stream5:2, AES_OUT, [PeripheralToMemory]), //AES_OUT +); + +#[cfg(feature = "cryp")] +dma_map!( + (Stream6:2, CRYP_IN, [MemoryToPeripheral]), //CRYP_IN + (Stream5:2, CRYP_OUT, [PeripheralToMemory]), //CRYP_OUT +); + +/*#[cfg(feature = "hash")] +dma_map!( + (Stream7:2, HASH_IN, [MemoryToPeripheral]), //HASH_IN +);*/ + +#[cfg(feature = "dfsdm1")] +use crate::pac::DFSDM; +#[cfg(feature = "dfsdm1")] +dma_map!( + (Stream0:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT0 + (Stream1:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT1 + (Stream2:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT2 + (Stream3:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT3 + (Stream4:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT0 + (Stream5:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT1 + (Stream6:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT2 + (Stream7:8, FLT, [PeripheralToMemory]), //DFSDM1_FLT3 +); +#[cfg(feature = "gpio-f76x")] +dma_map!( + (Stream0:8, pac::I2C3, [MemoryToPeripheral]), //I2C3_TX + (Stream1:8, pac::I2C4, [PeripheralToMemory]), //I2C4_RX + (Stream4:8, pac::I2C2, [MemoryToPeripheral]), //I2C2_TX + (Stream6:8, pac::I2C4, [MemoryToPeripheral]), //I2C4_TX + (Stream1:9, pac::SPI2, [PeripheralToMemory]), //SPI2_RX + (Stream6:9, pac::SPI2, [MemoryToPeripheral]), //SPI2_TX + + (Stream0:10, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_B + (Stream1:10, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI2_B + (Stream2:10, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI2_A + (Stream6:10, SAICH, [MemoryToPeripheral | PeripheralToMemory]), //SAI1_A + + (Stream2:11, pac::QUADSPI, [MemoryToPeripheral | PeripheralToMemory]), //QUADSPI + +); +/* +#[cfg(feature = "jpeg")] +dma_map!( + (Stream0:9, FLT, [MemoryToPeripheral]), //JPEG_IN + (Stream1:9, FLT, [PeripheralToMemory]), //JPEG_OUT + (Stream3:9, FLT, [MemoryToPeripheral]), //JPEG_IN + (Stream4:9, FLT, [PeripheralToMemory]), //JPEG_OUT +); +*/ diff --git a/src/flash.rs b/src/flash/f4.rs similarity index 100% rename from src/flash.rs rename to src/flash/f4.rs diff --git a/src/flash/f7.rs b/src/flash/f7.rs new file mode 100644 index 00000000..15870742 --- /dev/null +++ b/src/flash/f7.rs @@ -0,0 +1,301 @@ +//! Flash memory + +use crate::pac::FLASH; +use nb::block; + +/// Base address of flash memory on AXIM interface. +const FLASH_BASE: *mut u8 = 0x800_0000 as *mut u8; + +/// The last valid flash address in any STM32F7 device +const MAX_FLASH_ADDRESS: *mut u8 = 0x81F_FFFF as *mut u8; + +/// Flash programming error. +#[derive(Debug, PartialEq, Eq)] +pub enum Error { + Busy, + Locked, + EraseSequence, + ProgrammingParallelism, + ProgrammingAlignment, + WriteProtection, +} + +/// Embedded flash memory. +pub struct Flash { + registers: FLASH, +} + +impl Flash { + /// Creates a new Flash instance. + pub fn new(flash: FLASH) -> Self { + Self { registers: flash } + } + + /// Unlocks the flash memory. + pub fn unlock(&mut self) { + if !self.is_locked() { + // don't try to unlock the flash if it's already unlocked, because + // trying to unlock the flash twice causes a HardFault + return; + } + + self.registers.keyr().write(|w| w.key().set(0x45670123)); + self.registers.keyr().write(|w| w.key().set(0xCDEF89AB)); + } + + /// Locks the flash memory. + pub fn lock(&mut self) { + self.registers.cr().modify(|_, w| w.lock().set_bit()); + } + + /// Returns `true` if the flash memory is locked. + fn is_locked(&self) -> bool { + self.registers.cr().read().lock().is_locked() + } + + /// Returns `true` if a flash operation is in progress. + fn is_busy(&self) -> bool { + self.registers.sr().read().bsy().bit_is_set() + } + + /// Starts a sector erase sequence. + /// + /// The returned `EraseSequence` object can be used to wait for the completion of the + /// erase sequence by blocking on the `wait` method. + pub fn erase_sector(&mut self, sector_number: u8) -> Result, Error> { + EraseSequence::new_erase_sector(self, sector_number) + } + + /// Erases a flash sector. + /// + /// This method blocks until the sector is erased or an error occurred. + pub fn blocking_erase_sector(&mut self, sector_number: u8) -> Result<(), Error> { + let mut sequence = self.erase_sector(sector_number)?; + block!(sequence.wait()) + } + + /// Starts a mass erases of the flash memory. + /// + /// The returned `EraseSequence` object can be used to wait for the completion of the + /// erase sequence by blocking on the `wait` method. + pub fn mass_erase(&mut self) -> Result, Error> { + EraseSequence::new_mass_erase(self) + } + + /// Mass erases the flash memory. + /// + /// This method blocks until the flash is erased or an error occurred. + pub fn blocking_mass_erase(&mut self) -> Result<(), Error> { + let mut sequence = self.mass_erase()?; + block!(sequence.wait()) + } + + /// Starts a programming sequence. + /// + /// Note that you must block on the `wait` method in the returned `ProgrammingSequence` object + /// in order to program all bytes. + pub fn program<'a, 'b>( + &'a mut self, + start_offset: usize, + data: &'b [u8], + ) -> Result, Error> { + ProgrammingSequence::new(self, start_offset, data) + } + + /// Programs a block of flash memory. + /// + /// This method blocks until the block is programed or an error occurred. + pub fn blocking_program(&mut self, start_offset: usize, data: &[u8]) -> Result<(), Error> { + let mut sequence = self.program(start_offset, data)?; + block!(sequence.wait()) + } + + /// Releases the flash peripheral. + pub fn free(self) -> FLASH { + self.registers + } + + /// Returns an error if the flash is locked or busy. + fn check_locked_or_busy(&self) -> Result<(), Error> { + if self.is_locked() { + Err(Error::Locked) + } else if self.is_busy() { + Err(Error::Busy) + } else { + Ok(()) + } + } + + /// Checks the error flags. + fn check_errors(&self) -> Result<(), Error> { + let sr = self.registers.sr().read(); + + if sr.erserr().bit_is_set() { + Err(Error::EraseSequence) + } else if sr.pgperr().bit_is_set() { + Err(Error::ProgrammingParallelism) + } else if sr.pgaerr().bit_is_set() { + Err(Error::ProgrammingAlignment) + } else if sr.wrperr().bit_is_set() { + Err(Error::WriteProtection) + } else { + Ok(()) + } + } + + /// Clears all error flags. + fn clear_errors(&mut self) { + self.registers.sr().write(|w| { + w.erserr().clear_bit_by_one(); + w.pgperr().clear_bit_by_one(); + w.pgaerr().clear_bit_by_one(); + w.wrperr().clear_bit_by_one() + }); + } +} + +/// Erase sequence. +pub struct EraseSequence<'a> { + flash: &'a mut Flash, +} + +impl<'a> EraseSequence<'a> { + /// Creates a sector erase sequence. + fn new_erase_sector(flash: &'a mut Flash, sector_number: u8) -> Result { + flash.check_locked_or_busy()?; + flash.clear_errors(); + + //TODO: This should check if sector_number is valid for this device + + flash.registers.cr().modify(|_, w| unsafe { + #[cfg(any( + feature = "stm32f765", + feature = "stm32f767", + feature = "stm32f769", + feature = "stm32f777", + feature = "stm32f778", + feature = "stm32f779", + ))] + w.mer1().clear_bit().mer2().clear_bit(); + #[cfg(not(any( + feature = "stm32f765", + feature = "stm32f767", + feature = "stm32f769", + feature = "stm32f777", + feature = "stm32f778", + feature = "stm32f779", + )))] + w.mer().clear_bit(); + w.ser().set_bit(); + w.snb().bits(sector_number) + }); + flash.registers.cr().modify(|_, w| w.strt().start()); + + Ok(Self { flash }) + } + + /// Creates a mass erase sequence. + fn new_mass_erase(flash: &'a mut Flash) -> Result { + flash.check_locked_or_busy()?; + flash.clear_errors(); + + flash.registers.cr().modify(|_, w| { + #[cfg(any( + feature = "stm32f765", + feature = "stm32f767", + feature = "stm32f769", + feature = "stm32f777", + feature = "stm32f778", + feature = "stm32f779", + ))] + w.mer1().set_bit().mer2().set_bit(); + #[cfg(not(any( + feature = "stm32f765", + feature = "stm32f767", + feature = "stm32f769", + feature = "stm32f777", + feature = "stm32f778", + feature = "stm32f779", + )))] + w.mer().clear_bit(); + w.ser().clear_bit() + }); + + flash.registers.cr().modify(|_, w| w.strt().start()); + + Ok(Self { flash }) + } + + /// Waits until the erase sequence is finished. + pub fn wait(&mut self) -> nb::Result<(), Error> { + self.flash.check_errors().map_err(nb::Error::from)?; + + if self.flash.is_busy() { + Err(nb::Error::WouldBlock) + } else { + Ok(()) + } + } +} + +/// Programming sequence. +pub struct ProgrammingSequence<'a, 'b> { + flash: &'a mut Flash, + data: &'b [u8], + address: *mut u8, +} + +impl<'a, 'b> ProgrammingSequence<'a, 'b> { + /// Creates a programming sequence. + fn new(flash: &'a mut Flash, start_offset: usize, data: &'b [u8]) -> Result { + flash.check_locked_or_busy()?; + flash.clear_errors(); + + flash + .registers + .cr() + .modify(|_, w| w.psize().psize8().pg().set_bit()); + + let address = unsafe { FLASH_BASE.add(start_offset) }; + + Ok(Self { + flash, + data, + address, + }) + } + + /// Waits until the programming sequence is finished. + pub fn wait(&mut self) -> nb::Result<(), Error> { + if self.flash.is_busy() { + return Err(nb::Error::WouldBlock); + } + + if let Err(error) = self.flash.check_errors() { + // make sure programing mode is disabled when an error occurred + self.flash.registers.cr().modify(|_, w| w.pg().clear_bit()); + + return Err(error.into()); + } + + if let Some((first, rest)) = self.data.split_first() { + if self.address >= FLASH_BASE && self.address <= MAX_FLASH_ADDRESS { + unsafe { + core::ptr::write_volatile(self.address, *first); + } + } + + // ensure data is written byte by byte to prevent programming parallelism errors + cortex_m::asm::dmb(); + + self.address = unsafe { self.address.add(1) }; + self.data = rest; + + Err(nb::Error::WouldBlock) + } else { + self.flash.registers.cr().modify(|_, w| w.pg().clear_bit()); + + Ok(()) + } + } +} diff --git a/src/fmc.rs b/src/fmc.rs index 93c9bdea..86d4a1c0 100644 --- a/src/fmc.rs +++ b/src/fmc.rs @@ -163,7 +163,12 @@ pins! { NWE: Nwe; } -#[cfg(any(feature = "gpio-f427", feature = "gpio-f446", feature = "gpio-f469"))] +#[cfg(any( + feature = "f7", + feature = "gpio-f427", + feature = "gpio-f446", + feature = "gpio-f469" +))] pins! { BA0: Ba0; BA1: Ba1; @@ -177,7 +182,7 @@ pins! { SDNWE: Sdnwe; } -#[cfg(any(feature = "gpio-f427", feature = "gpio-f469"))] +#[cfg(any(feature = "f7", feature = "gpio-f427", feature = "gpio-f469"))] pins! { D16: D16; D17: D17; @@ -199,7 +204,7 @@ pins! { NBL3: Nbl3; } -#[cfg(feature = "gpio-f469")] +#[cfg(any(feature = "f7", feature = "gpio-f469"))] pins! { INT: Int; } @@ -217,3 +222,7 @@ pins! { pins! { NCE: Nce2; } +#[cfg(feature = "f7")] +pins! { + NCE: Nce; +} diff --git a/src/fmpi2c.rs b/src/fmpi2c.rs index d455498c..fe3c109b 100644 --- a/src/fmpi2c.rs +++ b/src/fmpi2c.rs @@ -1,8 +1,10 @@ use core::ops::Deref; use crate::gpio; - +#[cfg(feature = "fmpi2c1")] use crate::pac::fmpi2c1 as i2c1; +#[cfg(feature = "i2c_v2")] +use crate::pac::i2c1; use crate::pac::{self, rcc, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use fugit::{HertzU32 as Hertz, RateExtU32}; @@ -22,7 +24,10 @@ mod hal_02; #[path = "i2c/hal_1.rs"] mod hal_1; +#[cfg(feature = "fmpi2c1")] type I2cSel = rcc::dckcfgr2::FMPI2C1SEL; +#[cfg(feature = "i2c_v2")] +type I2cSel = rcc::dckcfgr2::I2C1SEL; pub trait Instance: crate::Sealed @@ -50,6 +55,17 @@ macro_rules! i2c { #[cfg(feature = "fmpi2c1")] i2c!(pac::FMPI2C1, fmpi2c1sel, FMPI2c1); +#[cfg(feature = "i2c_v2")] +i2c!(pac::I2C1, i2c1sel, I2c1); +#[cfg(feature = "i2c_v2")] +#[cfg(feature = "i2c2")] +i2c!(pac::I2C2, i2c2sel, I2c2); +#[cfg(feature = "i2c_v2")] +#[cfg(feature = "i2c3")] +i2c!(pac::I2C3, i2c3sel, I2c3); +#[cfg(feature = "i2c_v2")] +#[cfg(feature = "i2c4")] +i2c!(pac::I2C4, i2c4sel, I2c4); /// I2C FastMode+ abstraction pub struct I2c { @@ -198,7 +214,7 @@ fn calculate_timing( let mut presc: u8; // if ratio is > (scll+sclh)*presc. that frequancy is not possible to generate. so // minimum frequancy possible is generated - if product > 8192 as f32 { + if product > 8192_f32 { // TODO: should we panic or use minimum allowed frequancy scl_l = 0x7fu8; scl_h = 0x7fu8; @@ -214,7 +230,7 @@ fn calculate_timing( let deviation = product % tmp_presc as f32; if min_deviation > deviation { min_deviation = deviation; - presc = tmp_presc as u8; + presc = tmp_presc; } } // now that we have optimal prescalar value. optimal scl_l and scl_h diff --git a/src/gpio.rs b/src/gpio.rs index 9e30fd25..c5ac215e 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -618,9 +618,16 @@ macro_rules! gpio { } use gpio; +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f4")] pub use f4::*; +#[cfg(feature = "f7")] +mod f7; +#[cfg(feature = "f7")] +pub use f7::*; + const fn gpiox() -> *const crate::pac::gpioa::RegisterBlock { match P { 'A' => crate::pac::GPIOA::ptr(), diff --git a/src/gpio/alt.rs b/src/gpio/alt.rs index 25b91f92..c4f483b0 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1,6 +1,13 @@ +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f4")] pub use f4::*; +#[cfg(feature = "f7")] +mod f7; +#[cfg(feature = "f7")] +pub use f7::*; + macro_rules! extipin { ($( $(#[$attr:meta])* $PX:ident,)*) => { fn make_interrupt_source(&mut self, _syscfg: &mut $crate::syscfg::SysCfg) { diff --git a/src/gpio/alt/f7.rs b/src/gpio/alt/f7.rs new file mode 100644 index 00000000..3c42d0ac --- /dev/null +++ b/src/gpio/alt/f7.rs @@ -0,0 +1,3475 @@ +use super::*; +use crate::gpio::{self, NoPin, OpenDrain, PushPull}; + +pub mod can1 { + use super::*; + + pin! { + for no:NoPin, [ + PA11<9>, + + PB8<9>, + + PD0<9>, + + #[cfg(any(feature = "gpio-f72x", feature = "gpio-f76x"))] + PH14<9>, + + PI9<9>, + ], + + for no:NoPin, [ + PA12<9>, + + PB9<9>, + + PD1<9>, + + PH13<9>, + ], + } + impl CanCommon for crate::pac::CAN1 { + type Rx = Rx; + type Tx = Tx; + } +} + +#[cfg(feature = "can2")] +pub mod can2 { + use super::*; + + pin! { + for no:NoPin, [ + PB5<9>, + + PB12<9>, + ], + + for no:NoPin, [ + PB6<9>, + + PB13<9>, + ], + } + impl CanCommon for crate::pac::CAN2 { + type Rx = Rx; + type Tx = Tx; + } +} + +#[cfg(feature = "can3")] +pub mod can3 { + use super::*; + + pin! { + for no:NoPin, [ + PA8<11>, + + PB3<11>, + ], + + for no:NoPin, [ + PA15<11>, + + PB4<11>, + ], + } + impl CanCommon for crate::pac::CAN3 { + type Rx = Rx; + type Tx = Tx; + } +} + +#[cfg(feature = "dcmi")] +pub mod dcmi { + use super::*; + + pin! { + for [ + PA9<13>, + + PC6<13>, + + PH9<13>, + ], + + for [ + PA10<13>, + + PC7<13>, + + PH10<13>, + ], + + for [ + PB5<13>, + + PD6<13>, + + PI3<13>, + ], + + for [ + PD2<13>, + + PF10<13>, + + PH15<13>, + ], + + for [ + PF11<13>, + + PG6<13>, + ], + + for [ + PG7<13>, + + PG15<13>, + + PI0<13>, + ], + + for [ + PC8<13>, + + PE0<13>, + + PG10<13>, + + PH11<13>, + ], + + for [ + PC9<13>, + + PE1<13>, + + PG11<13>, + + PH12<13>, + ], + + for [ + PC11<13>, + + PE4<13>, + + PH14<13>, + ], + + for [ + PB6<13>, + + PD3<13>, + + PI4<13>, + ], + + for [ + PB8<13>, + + PE5<13>, + + PI6<13>, + ], + + for [ + PB9<13>, + + PE6<13>, + + PI7<13>, + ], + + for [ + PC10<13>, + + PH6<13>, + + PI1<13>, + ], + + for [ + PC12<13>, + + PH7<13>, + + PI2<13>, + ], + + for [ + PA4<13>, + + PH8<13>, + ], + + for [ + PA6<13>, + ], + + for [ + PB7<13>, + + PG9<13>, + + PI5<13>, + ], + } +} + +#[cfg(feature = "dfsdm1")] +pub mod dfsdm1 { + use super::*; + + pin! { + for [ + PC0<3>, + + PD4<6>, + ], + + for [ + PB2<10>, + + PB13<6>, + + PC2<3>, + + PD7<6>, + ], + + for [ + PB15<6>, + + PC4<3>, + + PE8<6>, + ], + + for [ + PC6<7>, + + PD8<3>, + + PE5<10>, + ], + + for [ + PC1<10>, + + PD6<3>, + + PE11<6>, + ], + + for [ + PB7<6>, + + PC10<3>, + + PE13<6>, + ], + + for [ + PD0<3>, + + PF14<6>, + ], + + for [ + PB8<6>, + + PB11<6>, + + PD1<6>, + ], + + for [ + PB0<6>, + + PC2<6>, + + PD3<3>, + + PD10<3>, + + PE9<6>, + ], + + for [ + PC1<3>, + + PD3<6>, + ], + + for [ + PB1<6>, + + PB12<6>, + + PC3<3>, + + PD6<10>, + ], + + for [ + PB14<6>, + + PC5<3>, + + PE7<6>, + ], + + for [ + PC7<7>, + + PD9<3>, + + PE4<10>, + ], + + for [ + PC0<6>, + + PD7<3>, + + PE10<6>, + ], + + for [ + PB6<6>, + + PC11<3>, + + PE12<6>, + ], + + for [ + PD1<3>, + + PF13<6>, + ], + + for [ + PB9<6>, + + PB10<6>, + + PD0<6>, + ], + } + + #[cfg(not(feature = "stm32f765"))] + use crate::pac::DFSDM; + #[cfg(feature = "stm32f765")] + use crate::pac::DFSDM1 as DFSDM; + impl DfsdmBasic for DFSDM { + type Ckin0 = Ckin0; + type Ckin1 = Ckin1; + type Ckout = Ckout; + type Datin0 = Datin0; + type Datin1 = Datin1; + } + impl DfsdmGeneral for DFSDM { + type Ckin2 = Ckin2; + type Ckin3 = Ckin3; + type Datin2 = Datin2; + type Datin3 = Datin3; + } + + impl DfsdmAdvanced for DFSDM { + type Ckin4 = Ckin4; + type Ckin5 = Ckin5; + type Ckin6 = Ckin6; + type Ckin7 = Ckin7; + type Datin4 = Datin4; + type Datin5 = Datin5; + type Datin6 = Datin6; + type Datin7 = Datin7; + } +} + +#[cfg(feature = "dsihost")] +pub mod dsihost { + use super::*; + + pin! { + for [ + PB11<13>, + + PJ2<13>, + ], + } +} + +#[cfg(feature = "eth")] +pub mod eth { + use super::*; + + pin! { + for [ + PA3<11>, + + PH3<11>, + ], + + for [ + PA0<11>, + + PH2<11>, + ], + + for [ + PA7<11>, + ], + + for [ + PC1<11>, + ], + + for [ + PA2<11>, + ], + + for [ + PB5<11>, + + PG8<11>, + ], + + for [ + PA1<11>, + ], + + for [ + PA1<11>, + ], + + for [ + PA7<11>, + ], + + for [ + PB10<11>, + + PI10<11>, + ], + + for [ + PC4<11>, + ], + + for [ + PC5<11>, + ], + + for [ + PB0<11>, + + PH6<11>, + ], + + for [ + PB1<11>, + + PH7<11>, + ], + + for [ + PC3<11>, + ], + + for [ + PB11<11>, + + PG11<11>, + ], + + for [ + PB12<11>, + + PG13<11>, + ], + + for [ + PB13<11>, + + PG14<11>, + ], + + for [ + PC2<11>, + ], + + for [ + PB8<11>, + + PE2<11>, + ], + } +} + +pub mod fmc { + use super::*; + + // TODO: replace this with `Ax` + pin! { + /// A pin that can be used as one bit of the memory address + /// + /// This is used to switch between data and command mode. + for [ + PD11<12, Speed::VeryHigh>, + PD12<12, Speed::VeryHigh>, + PD13<12, Speed::VeryHigh>, + PE2<12, Speed::VeryHigh>, + PE3<12, Speed::VeryHigh>, + PE4<12, Speed::VeryHigh>, + PE5<12, Speed::VeryHigh>, + PE6<12, Speed::VeryHigh>, + PF0<12, Speed::VeryHigh>, + PF1<12, Speed::VeryHigh>, + PF2<12, Speed::VeryHigh>, + PF3<12, Speed::VeryHigh>, + PF4<12, Speed::VeryHigh>, + PF5<12, Speed::VeryHigh>, + PF12<12, Speed::VeryHigh>, + PF13<12, Speed::VeryHigh>, + PF14<12, Speed::VeryHigh>, + PF15<12, Speed::VeryHigh>, + PG0<12, Speed::VeryHigh>, + PG1<12, Speed::VeryHigh>, + PG2<12, Speed::VeryHigh>, + PG3<12, Speed::VeryHigh>, + PG4<12, Speed::VeryHigh>, + PG5<12, Speed::VeryHigh>, + PG13<12, Speed::VeryHigh>, + ], + } + + pin! { + for [ + PF0<12, Speed::VeryHigh>, + ], + + for [ + PF1<12, Speed::VeryHigh>, + ], + + for [ + PF2<12, Speed::VeryHigh>, + ], + + for [ + PF3<12, Speed::VeryHigh>, + ], + + for [ + PF4<12, Speed::VeryHigh>, + ], + + for [ + PF5<12, Speed::VeryHigh>, + ], + + for [ + PF12<12, Speed::VeryHigh>, + ], + + for [ + PF13<12, Speed::VeryHigh>, + ], + + for [ + PF14<12, Speed::VeryHigh>, + ], + + for [ + PF15<12, Speed::VeryHigh>, + ], + + for [ + PG0<12, Speed::VeryHigh>, + ], + + for [ + PG1<12, Speed::VeryHigh>, + ], + + for [ + PG2<12, Speed::VeryHigh>, + ], + + for [ + PG3<12, Speed::VeryHigh>, + ], + + for [ + PG4<12, Speed::VeryHigh>, + ], + + for [ + PG5<12, Speed::VeryHigh>, + ], + + for [ + PD11<12, Speed::VeryHigh>, + ], + + for [ + PD12<12, Speed::VeryHigh>, + ], + + for [ + PD13<12, Speed::VeryHigh>, + ], + + for [ + PE3<12, Speed::VeryHigh>, + ], + + for [ + PE4<12, Speed::VeryHigh>, + ], + + for [ + PE5<12, Speed::VeryHigh>, + ], + + for [ + PE6<12, Speed::VeryHigh>, + ], + + for [ + PE2<12, Speed::VeryHigh>, + ], + + for [ + PG13<12, Speed::VeryHigh>, + ], + + for [ + PG14<12, Speed::VeryHigh>, + ], + + for [ + PD12<12, Speed::VeryHigh>, + ], + + for [ + PG4<12, Speed::VeryHigh>, + ], + + for [ + PG5<12, Speed::VeryHigh>, + ], + + for [ + PD11<12, Speed::VeryHigh>, + ], + + for [ + PD3<12, Speed::VeryHigh>, + ], + + for [ + PD14<12, Speed::VeryHigh>, + ], + + for [ + PD15<12, Speed::VeryHigh>, + ], + + for [ + PD0<12, Speed::VeryHigh>, + ], + + for [ + PD1<12, Speed::VeryHigh>, + ], + + for [ + PE7<12, Speed::VeryHigh>, + ], + + for [ + PE8<12, Speed::VeryHigh>, + ], + + for [ + PE9<12, Speed::VeryHigh>, + ], + + for [ + PE10<12, Speed::VeryHigh>, + ], + + for [ + PE11<12, Speed::VeryHigh>, + ], + + for [ + PE12<12, Speed::VeryHigh>, + ], + + for [ + PE13<12, Speed::VeryHigh>, + ], + + for [ + PE14<12, Speed::VeryHigh>, + ], + + for [ + PE15<12, Speed::VeryHigh>, + ], + + for [ + PD8<12, Speed::VeryHigh>, + ], + + for [ + PD9<12, Speed::VeryHigh>, + ], + + for [ + PD10<12, Speed::VeryHigh>, + ], + + for [ + PH8<12, Speed::VeryHigh>, + ], + + for [ + PH9<12, Speed::VeryHigh>, + ], + + for [ + PH10<12, Speed::VeryHigh>, + ], + + for [ + PH11<12, Speed::VeryHigh>, + ], + + for [ + PH12<12, Speed::VeryHigh>, + ], + + for [ + PH13<12, Speed::VeryHigh>, + ], + + for [ + PH14<12, Speed::VeryHigh>, + ], + + for [ + PH15<12, Speed::VeryHigh>, + ], + + for [ + PI0<12, Speed::VeryHigh>, + ], + + for [ + PI1<12, Speed::VeryHigh>, + ], + + for [ + PI2<12, Speed::VeryHigh>, + ], + + for [ + PI3<12, Speed::VeryHigh>, + ], + + for [ + PI6<12, Speed::VeryHigh>, + ], + + for [ + PI7<12, Speed::VeryHigh>, + ], + + for [ + PI9<12, Speed::VeryHigh>, + ], + + for [ + PI10<12, Speed::VeryHigh>, + ], + + for [ + PD14<12, Speed::VeryHigh>, + ], + + for [ + PD15<12, Speed::VeryHigh>, + ], + + for [ + PD0<12, Speed::VeryHigh>, + ], + + for [ + PD1<12, Speed::VeryHigh>, + ], + + for [ + PE7<12, Speed::VeryHigh>, + ], + + for [ + PE8<12, Speed::VeryHigh>, + ], + + for [ + PE9<12, Speed::VeryHigh>, + ], + + for [ + PE10<12, Speed::VeryHigh>, + ], + + for [ + PE11<12, Speed::VeryHigh>, + ], + + for [ + PE12<12, Speed::VeryHigh>, + ], + + for [ + PE13<12, Speed::VeryHigh>, + ], + + for [ + PE14<12, Speed::VeryHigh>, + ], + + for [ + PE15<12, Speed::VeryHigh>, + ], + + for [ + PD8<12, Speed::VeryHigh>, + ], + + for [ + PD9<12, Speed::VeryHigh>, + ], + + for [ + PD10<12, Speed::VeryHigh>, + ], + + for [ + PG7<12, Speed::VeryHigh>, + + #[cfg(feature = "gpio-f72x")] + PG11<12, Speed::VeryHigh>, + ], + + for [ + PE0<12, Speed::VeryHigh>, + ], + + for [ + PE1<12, Speed::VeryHigh>, + ], + + for [ + PI4<12, Speed::VeryHigh>, + ], + + for [ + PI5<12, Speed::VeryHigh>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC8<9, Speed::VeryHigh>, + + PG9<12, Speed::VeryHigh>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC7<9, Speed::VeryHigh>, + + PD7<12, Speed::VeryHigh>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC8<9, Speed::VeryHigh>, + + PG9<12, Speed::VeryHigh>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PG6<12, Speed::VeryHigh>, + + PG10<12, Speed::VeryHigh>, + ], + + for [ + PG12<12, Speed::VeryHigh>, + ], + + for [ + PB7<12, Speed::VeryHigh>, + ], + + for [ + PD4<12, Speed::VeryHigh>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC6<9, Speed::VeryHigh>, + + PD6<12, Speed::VeryHigh>, + ], + + for [ + PD5<12, Speed::VeryHigh>, + ], + + for [ + PC3<12, Speed::VeryHigh>, + + PC5<12, Speed::VeryHigh>, + + PH2<12, Speed::VeryHigh>, + ], + + for [ + PB5<12, Speed::VeryHigh>, + + PH7<12, Speed::VeryHigh>, + ], + + for [ + PG8<12, Speed::VeryHigh>, + ], + + for [ + PG15<12, Speed::VeryHigh>, + ], + + for [ + PC2<12, Speed::VeryHigh>, + + PC4<12, Speed::VeryHigh>, + + PH3<12, Speed::VeryHigh>, + ], + + for [ + PB6<12, Speed::VeryHigh>, + + PH6<12, Speed::VeryHigh>, + ], + + for [ + PF11<12, Speed::VeryHigh>, + ], + + for [ + PA7<12, Speed::VeryHigh>, + + PC0<12, Speed::VeryHigh>, + + PH5<12, Speed::VeryHigh>, + ], + } +} + +pub mod i2c1 { + use super::*; + + pin! { + for [ + PB6<4>, + + PB8<4>, + ], + + for [ + PB7<4>, + + PB9<4>, + ], + + for [ + PB5<4>, + ], + } + use crate::pac::I2C1 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2c2 { + use super::*; + + pin! { + for [ + PB10<4>, + + PF1<4>, + + PH4<4>, + ], + + for [ + PB11<4>, + + PF0<4>, + + PH5<4>, + ], + + for [ + PB12<4>, + + PF2<4>, + + PH6<4>, + ], + } + use crate::pac::I2C2 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2c3 { + use super::*; + + pin! { + for [ + PA8<4>, + + PH7<4>, + ], + + for [ + PC9<4>, + + PH8<4>, + ], + + for [ + PA9<4>, + + PH9<4>, + ], + } + use crate::pac::I2C3 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +#[cfg(feature = "i2c4")] +pub mod i2c4 { + use super::*; + + pin! { + for [ + #[cfg(feature = "gpio-f76x")] + PB6<11>, + + #[cfg(feature = "gpio-f76x")] + PB8<1>, + + PD12<4>, + + PF14<4>, + + PH11<4>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PB7<11>, + + #[cfg(feature = "gpio-f76x")] + PB9<1>, + + PD13<4>, + + PF15<4>, + + PH12<4>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PB9<11>, + + PD11<4>, + + PF13<4>, + + PH10<4>, + ], + } + use crate::pac::I2C4 as I2C; + impl I2cCommon for I2C { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +pub mod i2s { + use super::*; + + pin! { + for [ + PC9<5>, + ], + } +} + +pub mod i2s1 { + use super::*; + + pin! { + for [ + PA5<5>, + + PB3<5>, + + #[cfg(feature = "gpio-f76x")] + PG11<5>, + ], + + for no:NoPin, [ + PC4<5>, + ], + + for [ + PA7<5>, + + PB5<5>, + + #[cfg(feature = "gpio-f76x")] + PD7<5>, + ], + + for [ + PA4<5>, + + PA15<5>, + + #[cfg(feature = "gpio-f76x")] + PG10<5>, + ], + } + + use crate::pac::SPI1 as SPI; + + impl I2sCommon for SPI { + type Ck = Ck; + type Sd = Sd; + type Ws = Ws; + } + impl I2sMaster for SPI { + type Mck = Mck; + } +} + +pub mod i2s2 { + use super::*; + + pin! { + for [ + PA9<5>, + + #[cfg(feature = "gpio-f76x")] + PA12<5>, + + PB10<5>, + + PB13<5>, + + PD3<5>, + + PI1<5>, + ], + + for no:NoPin, [ + PC6<5>, + ], + + for [ + PB15<5>, + + PC1<5>, + + PC3<5>, + + PI3<5>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA11<5>, + + PB4<7>, + + PB9<5>, + + PB12<5>, + + PI0<5>, + ], + } + + use crate::pac::SPI2 as SPI; + + impl I2sCommon for SPI { + type Ck = Ck; + type Sd = Sd; + type Ws = Ws; + } + impl I2sMaster for SPI { + type Mck = Mck; + } +} + +pub mod i2s3 { + use super::*; + + pin! { + for [ + PB3<6>, + + PC10<6>, + ], + + for no:NoPin, [ + PC7<6>, + ], + + for [ + PB2<7>, + + PB5<6>, + + PC12<6>, + + PD6<5>, + ], + + for [ + PA4<6>, + + PA15<6>, + ], + } + + use crate::pac::SPI3 as SPI; + + impl I2sCommon for SPI { + type Ck = Ck; + type Sd = Sd; + type Ws = Ws; + } + impl I2sMaster for SPI { + type Mck = Mck; + } +} + +pub mod lptim1 { + use super::*; + + pin! { + for [ + PE0<3>, + + PG14<3>, + ], + + for [ + PD12<3>, + + PG12<3>, + ], + + for [ + PE1<3>, + + PH2<3>, + ], + } + + pin! { + default:PushPull for [ + PD13<3>, + + PG13<3>, + ], + } +} + +#[cfg(feature = "ltdc")] +pub mod ltdc { + use super::*; + + pin! { + for [ + PE4<14>, + + PG14<14>, + + PJ12<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA10<14>, + + PG12<14>, + + PJ13<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA3<9>, + + #[cfg(feature = "gpio-f76x")] + PC9<14>, + + PD6<14>, + + PG10<14>, + + PJ14<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA8<13>, + + PD10<14>, + + PG11<14>, + + PJ15<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA10<9>, + + PE12<14>, + + PG12<9>, + + PI4<14>, + + PK3<14>, + ], + + for [ + PA3<14>, + + PI5<14>, + + PK4<14>, + ], + + for [ + PB8<14>, + + PI6<14>, + + PK5<14>, + ], + + for [ + PB9<14>, + + PI7<14>, + + PK6<14>, + ], + + for [ + PE14<14>, + + PG7<14>, + + PI14<14>, + ], + + for [ + PE13<14>, + + PF10<14>, + + PK7<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PB1<14>, + + PE5<14>, + + PJ7<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PB0<14>, + + PE6<14>, + + PJ8<14>, + ], + + for [ + PA6<14>, + + PH13<14>, + + #[cfg(feature = "gpio-f76x")] + PI15<9>, + + PJ9<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC9<10>, + + PE11<14>, + + PG10<9>, + + PH14<14>, + + PJ10<14>, + + #[cfg(feature = "gpio-f76x")] + PJ12<9>, + ], + + for [ + PB10<14>, + + #[cfg(feature = "gpio-f76x")] + PH4<14>, + + PH15<14>, + + PJ11<14>, + + #[cfg(feature = "gpio-f76x")] + PJ13<9>, + ], + + for [ + PB11<14>, + + #[cfg(feature = "gpio-f76x")] + PH4<9>, + + PI0<14>, + + PK0<14>, + ], + + for [ + PC7<14>, + + PI1<14>, + + #[cfg(feature = "gpio-f76x")] + PI11<9>, + + PK1<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PB5<14>, + + PD3<14>, + + #[cfg(feature = "gpio-f76x")] + PG8<14>, + + PI2<14>, + + PK2<14>, + ], + + for [ + PC6<14>, + + PI10<14>, + + PI12<14>, + ], + + for [ + PG13<14>, + + PH2<14>, + + PI15<14>, + ], + + for [ + PA2<14>, + + PH3<14>, + + PJ0<14>, + ], + + for [ + PA1<14>, + + PC10<14>, + + PH8<14>, + + PJ1<14>, + ], + + for [ + PB0<9>, + + PH9<14>, + + PJ2<14>, + ], + + for [ + PA5<14>, + + PA11<14>, + + PH10<14>, + + PJ3<14>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA9<14>, + + PA12<14>, + + PC0<14>, + + PH11<14>, + + PJ4<14>, + ], + + for [ + PA8<14>, + + PB1<9>, + + PH12<14>, + + PJ5<14>, + ], + + for [ + PE15<14>, + + PG6<14>, + + #[cfg(feature = "gpio-f76x")] + PJ0<9>, + + PJ6<14>, + ], + + for [ + PA4<14>, + + PI9<14>, + + PI13<14>, + ], + } +} + +#[cfg(feature = "mdios")] +pub mod mdios { + use super::*; + + pin! { + for [ + PA6<12>, + + PC1<12>, + ], + + for [ + PA2<12>, + + PA10<12>, + ], + } +} + +pub mod quadspi { + use super::*; + + pin! { + for [ + PC9<9>, + + PD11<9>, + + PF8<10>, + ], + + for [ + PC10<9>, + + PD12<9>, + + PF9<10>, + ], + + for [ + PE2<9>, + + PF7<9>, + ], + + for [ + PA1<9>, + + PD13<9>, + + PF6<9>, + ], + + for [ + PB6<10>, + + #[cfg(feature = "gpio-f76x")] + PB10<9>, + ], + + for [ + PE7<10>, + + PH2<9>, + ], + + for [ + PE8<10>, + + PH3<9>, + ], + + for [ + PE9<10>, + + PG9<9>, + ], + + for [ + PE10<10>, + + PG14<9>, + ], + + for [ + PC11<9>, + ], + + for [ + PB2<9>, + + #[cfg(feature = "gpio-f76x")] + PF10<9>, + ], + } + + pub struct Bank1; + pub struct Bank2; + + impl QuadSpiBanks for crate::pac::QUADSPI { + type Bank1 = Bank1; + type Bank2 = Bank2; + } + impl QuadSpiBank for Bank1 { + type Io0 = Bk1Io0; + type Io1 = Bk1Io1; + type Io2 = Bk1Io2; + type Io3 = Bk1Io3; + type Ncs = Bk1Ncs; + } + impl QuadSpiBank for Bank2 { + type Io0 = Bk2Io0; + type Io1 = Bk2Io1; + type Io2 = Bk2Io2; + type Io3 = Bk2Io3; + type Ncs = Bk2Ncs; + } +} + +pub mod rcc { + use super::*; + + pin! { + for [ + PA8<0>, + ], + + for [ + PC9<0>, + ], + } +} + +pub mod rtc { + use super::*; + + pin! { + for [ + PB15<0>, + ], + } +} + +pub mod sai1 { + use super::*; + + pin! { + for [ + PE4<6>, + ], + + for [ + PF9<6>, + ], + + for no:NoPin, [ + PE2<6>, + + #[cfg(feature = "gpio-f76x")] + PG7<6>, + ], + + for no:NoPin, [ + PF7<6>, + ], + + for [ + PE5<6>, + ], + + for [ + PF8<6>, + ], + + for [ + PB2<6>, + + PC1<6>, + + PD6<6>, + + PE6<6>, + ], + + for [ + PE3<6>, + + PF6<6>, + ], + } + use crate::pac::SAI1 as SAI; + use crate::sai::SAICH; + impl SaiChannels for SAI { + type A = SAICH; + type B = SAICH; + } + impl SaiChannel for SAICH { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for SAICH { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } +} + +pub mod sai2 { + use super::*; + + pin! { + for [ + PD12<10>, + + PI7<10>, + ], + + for [ + PA12<8>, + + PC0<8>, + + PE13<10>, + + PG9<10>, + ], + + for no:NoPin, [ + PE0<10>, + + PI4<10>, + ], + + for no:NoPin, [ + PA1<10>, + + PE6<10>, + + PE14<10>, + + PH3<10>, + ], + + for [ + PD13<10>, + + PI5<10>, + ], + + for [ + PA2<8>, + + PE12<10>, + + PH2<10>, + ], + + for [ + PD11<10>, + + PI6<10>, + ], + + for [ + PA0<10>, + + PE11<10>, + + PF11<10>, + + PG10<10>, + ], + } + use crate::pac::SAI2 as SAI; + use crate::sai::SAICH; + impl SaiChannels for SAI { + type A = SAICH; + type B = SAICH; + } + impl SaiChannel for SAICH { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for SAICH { + type Fs = FsB; + type Mclk = MclkB; + type Sck = SckB; + type Sd = SdB; + } +} + +pub mod sdmmc1 { + use super::*; + + pin! { + for [ + PC12<12>, + ], + + for [ + PD2<12>, + ], + + for [ + PC8<12>, + ], + + for [ + PC9<12>, + ], + + for [ + PC10<12>, + ], + + for [ + PC11<12>, + ], + + for [ + PB8<12>, + ], + + for [ + PB9<12>, + ], + + for [ + PC6<12>, + ], + + for [ + PC7<12>, + ], + } +} + +#[cfg(feature = "sdmmc2")] +pub mod sdmmc2 { + use super::*; + + pin! { + for [ + PD6<11>, + ], + + for [ + PD7<11>, + ], + + for [ + PB14<10>, + + PG9<11>, + ], + + for [ + PB15<10>, + + PG10<11>, + ], + + for [ + PB3<10>, + + PG11<10>, + ], + + for [ + PB4<10>, + + PG12<11>, + ], + + for [ + PB8<10>, + ], + + for [ + PB9<10>, + ], + + for [ + PC6<10>, + ], + + for [ + PC7<10>, + ], + } +} + +#[cfg(feature = "spdifrx")] +pub mod spdifrx { + use super::*; + + pin! { + for [ + PD7<8>, + + PG11<7>, + ], + + for [ + PD8<8>, + + PG12<7>, + ], + + for [ + PC4<8>, + + PG8<7>, + ], + + for [ + PC5<8>, + + PG9<7>, + ], + } + + use crate::pac::SPDIFRX; + impl SPdifIn<0> for SPDIFRX { + type In = In0; + } + impl SPdifIn<1> for SPDIFRX { + type In = In1; + } + impl SPdifIn<2> for SPDIFRX { + type In = In2; + } + impl SPdifIn<3> for SPDIFRX { + type In = In3; + } +} + +pub mod spi1 { + use super::*; + + pin! { + for no:NoPin, [ + PA6<5>, + + PB4<5>, + + #[cfg(feature = "gpio-f76x")] + PG9<5>, + ], + + for no:NoPin, [ + PA7<5>, + + PB5<5>, + + #[cfg(feature = "gpio-f76x")] + PD7<5>, + ], + + for [ + PA4<5>, + + PA15<5>, + + #[cfg(feature = "gpio-f76x")] + PG10<5>, + ], + + for no:NoPin, [ + PA5<5>, + + PB3<5>, + + #[cfg(feature = "gpio-f76x")] + PG11<5>, + ], + } + impl SpiCommon for crate::pac::SPI1 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi2 { + use super::*; + + pin! { + for no:NoPin, [ + PB14<5>, + + PC2<5>, + + PI2<5>, + ], + + for no:NoPin, [ + PB15<5>, + + PC1<5>, + + PC3<5>, + + PI3<5>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA11<5>, + + PB4<7>, + + PB9<5>, + + PB12<5>, + + PI0<5>, + ], + + for no:NoPin, [ + PA9<5>, + + #[cfg(feature = "gpio-f76x")] + PA12<5>, + + PB10<5>, + + PB13<5>, + + PD3<5>, + + PI1<5>, + ], + } + impl SpiCommon for crate::pac::SPI2 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi3 { + use super::*; + + pin! { + for no:NoPin, [ + PB4<6>, + + PC11<6>, + ], + + for no:NoPin, [ + PB2<7>, + + PB5<6>, + + PC12<6>, + + PD6<5>, + ], + + for [ + PA4<6>, + + PA15<6>, + ], + + for no:NoPin, [ + PB3<6>, + + PC10<6>, + ], + } + impl SpiCommon for crate::pac::SPI3 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi4 { + use super::*; + + pin! { + for no:NoPin, [ + PE5<5>, + + PE13<5>, + ], + + for no:NoPin, [ + PE6<5>, + + PE14<5>, + ], + + for [ + PE4<5>, + + PE11<5>, + ], + + for no:NoPin, [ + PE2<5>, + + PE12<5>, + ], + } + impl SpiCommon for crate::pac::SPI4 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod spi5 { + use super::*; + + pin! { + for no:NoPin, [ + PF8<5>, + + PH7<5>, + ], + + for no:NoPin, [ + PF9<5>, + + PF11<5>, + ], + + for [ + PF6<5>, + + PH5<5>, + ], + + for no:NoPin, [ + PF7<5>, + + PH6<5>, + ], + } + impl SpiCommon for crate::pac::SPI5 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +#[cfg(feature = "spi6")] +pub mod spi6 { + use super::*; + + pin! { + for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PA6<8>, + + #[cfg(feature = "gpio-f76x")] + PB4<8>, + + PG12<5>, + ], + + for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PA7<8>, + + #[cfg(feature = "gpio-f76x")] + PB5<8>, + + PG14<5>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PA4<8>, + + #[cfg(feature = "gpio-f76x")] + PA15<7>, + + PG8<5>, + ], + + for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PA5<8>, + + #[cfg(feature = "gpio-f76x")] + PB3<8>, + + PG13<5>, + ], + } + impl SpiCommon for crate::pac::SPI6 { + type Miso = Miso; + type Mosi = Mosi; + type Nss = Nss; + type Sck = Sck; + } +} + +pub mod sys { + use super::*; + + pin! { + for [ + PA14<0>, + ], + + for [ + PA15<0>, + ], + + for [ + PB3<0>, + ], + + for [ + PA13<0>, + ], + + for [ + PB4<0>, + ], + + for [ + PE2<0>, + ], + + for [ + PC1<0>, + + PE3<0>, + + PG13<0>, + ], + + for [ + PC8<0>, + + PE4<0>, + + PG14<0>, + ], + + for [ + PD2<0>, + + PE5<0>, + ], + + for [ + PC12<0>, + + PE6<0>, + ], + } +} + +pub mod tim1 { + use super::*; + + pin! { + default:PushPull for [ + PA8<1>, + + PE9<1>, + ], + + default:PushPull for [ + PA7<1>, + + PB13<1>, + + PE8<1>, + ], + + default:PushPull for [ + PA9<1>, + + PE11<1>, + ], + + default:PushPull for [ + PB0<1>, + + PB14<1>, + + PE10<1>, + ], + + default:PushPull for [ + PA10<1>, + + PE13<1>, + ], + + default:PushPull for [ + PB1<1>, + + PB15<1>, + + PE12<1>, + ], + + default:PushPull for [ + PA11<1>, + + PE14<1>, + ], + } + + pin! { + for [ + PA6<1>, + + PB12<1>, + + PE15<1>, + ], + + for [ + PE6<1>, + ], + + for [ + PA12<1>, + + PE7<1>, + ], + } + + use crate::pac::TIM1 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimNCPin<1> for TIM { + type ChN = Ch2N; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimNCPin<2> for TIM { + type ChN = Ch3N; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim2 { + use super::*; + + pin! { + default:PushPull for [ + PA0<1>, + + PA5<1>, + + PA15<1>, + ], + + default:PushPull for [ + PA1<1>, + + PB3<1>, + ], + + default:PushPull for [ + PA2<1>, + + PB10<1>, + ], + + default:PushPull for [ + PA3<1>, + + PB11<1>, + ], + } + + pin! { + for [ + PA0<1>, + + PA5<1>, + + PA15<1>, + ], + } + + use crate::pac::TIM2 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim3 { + use super::*; + + pin! { + default:PushPull for [ + PA6<2>, + + PB4<2>, + + PC6<2>, + ], + + default:PushPull for [ + PA7<2>, + + PB5<2>, + + PC7<2>, + ], + + default:PushPull for [ + PB0<2>, + + PC8<2>, + ], + + default:PushPull for [ + PB1<2>, + + PC9<2>, + ], + } + + pin! { + for [ + PD2<2>, + ], + } + + use crate::pac::TIM3 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim4 { + use super::*; + + pin! { + default:PushPull for [ + PB6<2>, + + PD12<2>, + ], + + default:PushPull for [ + PB7<2>, + + PD13<2>, + ], + + default:PushPull for [ + PB8<2>, + + PD14<2>, + ], + + default:PushPull for [ + PB9<2>, + + PD15<2>, + ], + } + + pin! { + for [ + PE0<2>, + ], + } + + use crate::pac::TIM4 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim5 { + use super::*; + + pin! { + default:PushPull for [ + PA0<2>, + + PH10<2>, + ], + + default:PushPull for [ + PA1<2>, + + PH11<2>, + ], + + default:PushPull for [ + PA2<2>, + + PH12<2>, + ], + + default:PushPull for [ + PA3<2>, + + PI0<2>, + ], + } + + use crate::pac::TIM5 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } +} + +pub mod tim8 { + use super::*; + + pin! { + default:PushPull for [ + PC6<3>, + + PI5<3>, + ], + + default:PushPull for [ + PA5<3>, + + PA7<3>, + + PH13<3>, + ], + + default:PushPull for [ + PC7<3>, + + PI6<3>, + ], + + default:PushPull for [ + PB0<3>, + + PB14<3>, + + PH14<3>, + ], + + default:PushPull for [ + PC8<3>, + + PI7<3>, + ], + + default:PushPull for [ + PB1<3>, + + PB15<3>, + + PH15<3>, + ], + + default:PushPull for [ + PC9<3>, + + PI2<3>, + ], + } + + pin! { + for [ + PA6<3>, + + PI4<3>, + ], + + for [ + PA8<3>, + + PI1<3>, + ], + + for [ + PA0<3>, + + PI3<3>, + ], + } + + use crate::pac::TIM8 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimNCPin<0> for TIM { + type ChN = Ch1N; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimNCPin<1> for TIM { + type ChN = Ch2N; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimNCPin<2> for TIM { + type ChN = Ch3N; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + +pub mod tim9 { + use super::*; + + pin! { + default:PushPull for [ + PA2<3>, + + PE5<3>, + ], + + default:PushPull for [ + PA3<3>, + + PE6<3>, + ], + } + + use crate::pac::TIM9 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } +} + +pub mod tim10 { + use super::*; + + pin! { + default:PushPull for [ + PB8<3>, + + PF6<3>, + ], + } + + use crate::pac::TIM10 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod tim11 { + use super::*; + + pin! { + default:PushPull for [ + PB9<3>, + + PF7<3>, + ], + } + + use crate::pac::TIM11 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod tim12 { + use super::*; + + pin! { + default:PushPull for [ + PB14<9>, + + PH6<9>, + ], + + default:PushPull for [ + PB15<9>, + + PH9<9>, + ], + } + + use crate::pac::TIM12 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } +} + +pub mod tim13 { + use super::*; + + pin! { + default:PushPull for [ + PA6<9>, + + PF8<9>, + ], + } + + use crate::pac::TIM13 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod tim14 { + use super::*; + + pin! { + default:PushPull for [ + PA7<9>, + + PF9<9>, + ], + } + + use crate::pac::TIM14 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } +} + +pub mod usart1 { + use super::*; + + pin! { + for [ + PA8<7>, + ], + + for [ + PA11<7>, + ], + + for [ + PA12<7>, + ], + + for [ + PA12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA10<7>, + + PB7<7>, + + #[cfg(feature = "gpio-f76x")] + PB15<4>, + ], + + default:PushPull for no:NoPin, [ + PA9<7>, + + PB6<7>, + + #[cfg(feature = "gpio-f76x")] + PB14<4>, + ], + } + use crate::pac::USART1 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialFlowControl for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart2 { + use super::*; + + pin! { + for [ + PA4<7>, + + PD7<7>, + ], + + for [ + PA0<7>, + + PD3<7>, + ], + + for [ + PA1<7>, + + PD4<7>, + ], + + for [ + PA1<7>, + + PD4<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA3<7>, + + PD6<7>, + ], + + default:PushPull for no:NoPin, [ + PA2<7>, + + PD5<7>, + ], + } + use crate::pac::USART2 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialFlowControl for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart3 { + use super::*; + + pin! { + for [ + PB12<7>, + + PC12<7>, + + PD10<7>, + ], + + for [ + PB13<7>, + + PD11<7>, + ], + + for [ + PB14<7>, + + PD12<7>, + ], + + for [ + PB14<7>, + + PD12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PB11<7>, + + PC11<7>, + + PD9<7>, + ], + + default:PushPull for no:NoPin, [ + PB10<7>, + + PC10<7>, + + PD8<7>, + ], + } + use crate::pac::USART3 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialFlowControl for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart6 { + use super::*; + + pin! { + for [ + PC8<8>, + + PG7<8>, + ], + + for [ + PG13<8>, + + PG15<8>, + ], + + for [ + PG8<8>, + + PG12<8>, + ], + + for [ + PG8<8>, + + PG12<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PC7<8>, + + PG9<8>, + ], + + default:PushPull for no:NoPin, [ + PC6<8>, + + PG14<8>, + ], + } + use crate::pac::USART6 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialFlowControl for USART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart4 { + use super::*; + + pin! { + for [ + PB0<8>, + + #[cfg(feature = "gpio-f76x")] + PB15<8>, + ], + + for [ + PA15<8>, + + #[cfg(feature = "gpio-f76x")] + PB14<8>, + ], + + for [ + PA15<8>, + + #[cfg(feature = "gpio-f76x")] + PB14<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA1<8>, + + #[cfg(feature = "gpio-f76x")] + PA11<6>, + + PC11<8>, + + #[cfg(feature = "gpio-f76x")] + PD0<8>, + + #[cfg(any(feature = "gpio-f72x", feature = "gpio-f76x"))] + PH14<8>, + + #[cfg(any(feature = "gpio-f72x", feature = "gpio-f76x"))] + PI9<8>, + ], + + default:PushPull for no:NoPin, [ + PA0<8>, + + #[cfg(feature = "gpio-f76x")] + PA12<6>, + + PC10<8>, + + #[cfg(feature = "gpio-f76x")] + PD1<8>, + + #[cfg(any(feature = "gpio-f72x", feature = "gpio-f76x"))] + PH13<8>, + ], + } + use crate::pac::UART4 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialFlowControl for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart5 { + use super::*; + + pin! { + for [ + PC9<7>, + ], + + for [ + PC8<7>, + ], + + for [ + PC8<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PB5<1>, + + #[cfg(feature = "gpio-f76x")] + PB8<7>, + + #[cfg(feature = "gpio-f76x")] + PB12<8>, + + PD2<8>, + ], + + default:PushPull for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PB6<1>, + + #[cfg(feature = "gpio-f76x")] + PB9<7>, + + #[cfg(feature = "gpio-f76x")] + PB13<8>, + + PC12<8>, + ], + } + use crate::pac::UART5 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialFlowControl for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart7 { + use super::*; + + pin! { + for [ + PE10<8>, + + PF9<8>, + ], + + for [ + PE9<8>, + + PF8<8>, + ], + + for [ + PE9<8>, + + PF8<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PA8<12>, + + #[cfg(feature = "gpio-f76x")] + PB3<12>, + + PE7<8>, + + PF6<8>, + ], + + default:PushPull for no:NoPin, [ + #[cfg(feature = "gpio-f76x")] + PA15<12>, + + #[cfg(feature = "gpio-f76x")] + PB4<12>, + + PE8<8>, + + PF7<8>, + ], + } + use crate::pac::UART7 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialFlowControl for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod uart8 { + use super::*; + + pin! { + for [ + PD14<8>, + ], + + for [ + PD15<8>, + ], + + for [ + PD15<8>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PE0<8>, + ], + + default:PushPull for no:NoPin, [ + PE1<8>, + ], + } + use crate::pac::UART8 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialFlowControl for UART { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod otg_fs { + use super::*; + + pin! { + for [ + PA11<10>, + ], + + for [ + PA12<10>, + ], + + for [ + PA10<10>, + ], + + for [ + PA8<10>, + ], + } +} + +pub mod otg_hs { + use super::*; + + pin! { + for [ + PB14<12>, + ], + + for [ + PB15<12>, + ], + + for [ + PB12<12>, + ], + + for [ + PA4<12>, + ], + + for [ + PA5<10, Speed::VeryHigh>, + ], + + for [ + PA3<10, Speed::VeryHigh>, + ], + + for [ + PB0<10, Speed::VeryHigh>, + ], + + for [ + PB1<10, Speed::VeryHigh>, + ], + + for [ + PB10<10, Speed::VeryHigh>, + ], + + for [ + PB11<10, Speed::VeryHigh>, + ], + + for [ + PB12<10, Speed::VeryHigh>, + ], + + for [ + PB13<10, Speed::VeryHigh>, + ], + + for [ + PB5<10, Speed::VeryHigh>, + ], + + for [ + PC2<10, Speed::VeryHigh>, + + PI11<10, Speed::VeryHigh>, + ], + + for [ + PC3<10, Speed::VeryHigh>, + + PH4<10, Speed::VeryHigh>, + ], + + for [ + PC0<10, Speed::VeryHigh>, + ], + } +} diff --git a/src/gpio/f7.rs b/src/gpio/f7.rs new file mode 100644 index 00000000..06ee95b2 --- /dev/null +++ b/src/gpio/f7.rs @@ -0,0 +1,605 @@ +// auto-generated using codegen +// STM32CubeMX DB release: DB.6.0.50 +pub use super::*; + +pub use super::Input as DefaultMode; + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 10]), + PA1: (pa1, 1, [1, 2, 7, 8, 9, 10]), + PA2: (pa2, 2, [1, 2, 3, 7, 8]), + PA3: (pa3, 3, [1, 2, 3, 7, 10]), + PA4: (pa4, 4, [5, 6, 7, 12]), + PA5: (pa5, 5, [1, 3, 5, 10]), + PA6: (pa6, 6, [1, 2, 3, 5, 9]), + PA7: (pa7, 7, [1, 2, 3, 5, 9, 12]), + PA8: (pa8, 8, [0, 1, 3, 4, 7, 10]), + PA9: (pa9, 9, [1, 4, 5, 7]), + PA10: (pa10, 10, [1, 7, 10]), + PA11: (pa11, 11, [1, 7, 9, 10]), + PA12: (pa12, 12, [1, 7, 8, 9, 10]), + PA13: (pa13, 13, [0], super::Debugger), + PA14: (pa14, 14, [0], super::Debugger), + PA15: (pa15, 15, [0, 1, 5, 6, 8], super::Debugger), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 8, 10]), + PB1: (pb1, 1, [1, 2, 3, 10]), + PB2: (pb2, 2, [6, 7, 9]), + PB3: (pb3, 3, [0, 1, 5, 6, 10], super::Debugger), + PB4: (pb4, 4, [0, 2, 5, 6, 7, 10], super::Debugger), + PB5: (pb5, 5, [2, 4, 5, 6, 10, 12]), + PB6: (pb6, 6, [2, 4, 7, 10, 12]), + PB7: (pb7, 7, [2, 4, 7, 12]), + PB8: (pb8, 8, [2, 3, 4, 9, 10, 12]), + PB9: (pb9, 9, [2, 3, 4, 5, 9, 10, 12]), + PB10: (pb10, 10, [1, 4, 5, 7, 10]), + PB11: (pb11, 11, [1, 4, 7, 10]), + PB12: (pb12, 12, [1, 4, 5, 7, 10, 12]), + PB13: (pb13, 13, [1, 5, 7, 10]), + PB14: (pb14, 14, [1, 3, 5, 7, 9, 10, 12]), + PB15: (pb15, 15, [0, 1, 3, 5, 9, 10, 12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [8, 10, 12]), + PC1: (pc1, 1, [0, 5, 6]), + PC2: (pc2, 2, [5, 10, 12]), + PC3: (pc3, 3, [5, 10, 12]), + PC4: (pc4, 4, [5, 12]), + PC5: (pc5, 5, [12]), + PC6: (pc6, 6, [2, 3, 5, 8, 10, 12]), + PC7: (pc7, 7, [2, 3, 6, 8, 10, 12]), + PC8: (pc8, 8, [0, 2, 3, 7, 8, 12]), + PC9: (pc9, 9, [0, 2, 3, 4, 5, 7, 9, 12]), + PC10: (pc10, 10, [6, 7, 8, 9, 12]), + PC11: (pc11, 11, [6, 7, 8, 9, 12]), + PC12: (pc12, 12, [0, 6, 7, 8, 12]), + PC13: (pc13, 13, []), + PC14: (pc14, 14, []), + PC15: (pc15, 15, []), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [9, 12]), + PD1: (pd1, 1, [9, 12]), + PD2: (pd2, 2, [0, 2, 8, 12]), + PD3: (pd3, 3, [5, 7, 12]), + PD4: (pd4, 4, [7, 12]), + PD5: (pd5, 5, [7, 12]), + PD6: (pd6, 6, [5, 6, 7, 11, 12]), + PD7: (pd7, 7, [7, 11, 12]), + PD8: (pd8, 8, [7, 12]), + PD9: (pd9, 9, [7, 12]), + PD10: (pd10, 10, [7, 12]), + PD11: (pd11, 11, [7, 9, 10, 12]), + PD12: (pd12, 12, [2, 3, 7, 9, 10, 12]), + PD13: (pd13, 13, [2, 3, 9, 10, 12]), + PD14: (pd14, 14, [2, 8, 12]), + PD15: (pd15, 15, [2, 8, 12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 3, 8, 10, 12]), + PE1: (pe1, 1, [3, 8, 12]), + PE2: (pe2, 2, [0, 5, 6, 9, 12]), + PE3: (pe3, 3, [0, 6, 12]), + PE4: (pe4, 4, [0, 5, 6, 12]), + PE5: (pe5, 5, [0, 3, 5, 6, 12]), + PE6: (pe6, 6, [0, 1, 3, 5, 6, 10, 12]), + PE7: (pe7, 7, [1, 8, 10, 12]), + PE8: (pe8, 8, [1, 8, 10, 12]), + PE9: (pe9, 9, [1, 8, 10, 12]), + PE10: (pe10, 10, [1, 8, 10, 12]), + PE11: (pe11, 11, [1, 5, 10, 12]), + PE12: (pe12, 12, [1, 5, 10, 12]), + PE13: (pe13, 13, [1, 5, 10, 12]), + PE14: (pe14, 14, [1, 5, 10, 12]), + PE15: (pe15, 15, [1, 12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 12]), + PF1: (pf1, 1, [4, 12]), + PF2: (pf2, 2, [4, 12]), + PF3: (pf3, 3, [12]), + PF4: (pf4, 4, [12]), + PF5: (pf5, 5, [12]), + PF6: (pf6, 6, [3, 5, 6, 8, 9]), + PF7: (pf7, 7, [3, 5, 6, 8, 9]), + PF8: (pf8, 8, [5, 6, 8, 9, 10]), + PF9: (pf9, 9, [5, 6, 8, 9, 10]), + PF10: (pf10, 10, []), + PF11: (pf11, 11, [5, 10, 12]), + PF12: (pf12, 12, [12]), + PF13: (pf13, 13, [12]), + PF14: (pf14, 14, [12]), + PF15: (pf15, 15, [12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, [ + PG0: (pg0, 0, [12]), + PG1: (pg1, 1, [12]), + PG2: (pg2, 2, [12]), + PG3: (pg3, 3, [12]), + PG4: (pg4, 4, [12]), + PG5: (pg5, 5, [12]), + PG6: (pg6, 6, []), + PG7: (pg7, 7, [8, 12]), + PG8: (pg8, 8, [8, 12]), + PG9: (pg9, 9, [8, 9, 10, 11, 12]), + PG10: (pg10, 10, [10, 11, 12]), + PG11: (pg11, 11, [10, 12]), + PG12: (pg12, 12, [3, 8, 11, 12]), + PG13: (pg13, 13, [0, 3, 8, 12]), + PG14: (pg14, 14, [0, 3, 8, 9, 12]), + PG15: (pg15, 15, [8, 12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, []), + PH1: (ph1, 1, []), + PH2: (ph2, 2, [3, 9, 10, 12]), + PH3: (ph3, 3, [9, 10, 12]), + PH4: (ph4, 4, [4, 10]), + PH5: (ph5, 5, [4, 5, 12]), + PH6: (ph6, 6, [4, 5, 9, 12]), + PH7: (ph7, 7, [4, 5, 12]), + PH8: (ph8, 8, [4, 12]), + PH9: (ph9, 9, [4, 9, 12]), + PH10: (ph10, 10, [2, 12]), + PH11: (ph11, 11, [2, 12]), + PH12: (ph12, 12, [2, 12]), + PH13: (ph13, 13, [3, 8, 9, 12]), + PH14: (ph14, 14, [3, 8, 9, 12]), + PH15: (ph15, 15, [3, 12]), +]); + +#[cfg(feature = "gpio-f72x")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 5, 12]), + PI1: (pi1, 1, [3, 5, 12]), + PI2: (pi2, 2, [3, 5, 12]), + PI3: (pi3, 3, [3, 5, 12]), + PI4: (pi4, 4, [3, 10, 12]), + PI5: (pi5, 5, [3, 10, 12]), + PI6: (pi6, 6, [3, 10, 12]), + PI7: (pi7, 7, [3, 10, 12]), + PI8: (pi8, 8, []), + PI9: (pi9, 9, [8, 9, 12]), + PI10: (pi10, 10, [12]), + PI11: (pi11, 11, [10]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 10, 11]), + PA1: (pa1, 1, [1, 2, 7, 8, 9, 10, 11, 14]), + PA2: (pa2, 2, [1, 2, 3, 7, 8, 11, 14]), + PA3: (pa3, 3, [1, 2, 3, 7, 10, 11, 14]), + PA4: (pa4, 4, [5, 6, 7, 12, 13, 14]), + PA5: (pa5, 5, [1, 3, 5, 10, 14]), + PA6: (pa6, 6, [1, 2, 3, 5, 9, 13, 14]), + PA7: (pa7, 7, [1, 2, 3, 5, 9, 11, 12]), + PA8: (pa8, 8, [0, 1, 3, 4, 7, 10, 14]), + PA9: (pa9, 9, [1, 4, 5, 7, 13]), + PA10: (pa10, 10, [1, 7, 10, 13]), + PA11: (pa11, 11, [1, 7, 9, 10, 14]), + PA12: (pa12, 12, [1, 7, 8, 9, 10, 14]), + PA13: (pa13, 13, [0], super::Debugger), + PA14: (pa14, 14, [0], super::Debugger), + PA15: (pa15, 15, [0, 1, 4, 5, 6, 8], super::Debugger), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 8, 9, 10, 11]), + PB1: (pb1, 1, [1, 2, 3, 9, 10, 11]), + PB2: (pb2, 2, [6, 7, 9]), + PB3: (pb3, 3, [0, 1, 5, 6], super::Debugger), + PB4: (pb4, 4, [0, 2, 5, 6, 7], super::Debugger), + PB5: (pb5, 5, [2, 4, 5, 6, 9, 10, 11, 12, 13]), + PB6: (pb6, 6, [2, 3, 4, 7, 9, 10, 12, 13]), + PB7: (pb7, 7, [2, 4, 7, 12, 13]), + PB8: (pb8, 8, [2, 3, 4, 9, 11, 12, 13, 14]), + PB9: (pb9, 9, [2, 3, 4, 5, 9, 12, 13, 14]), + PB10: (pb10, 10, [1, 4, 5, 7, 10, 11, 14]), + PB11: (pb11, 11, [1, 4, 7, 10, 11, 14]), + PB12: (pb12, 12, [1, 4, 5, 7, 9, 10, 11, 12]), + PB13: (pb13, 13, [1, 5, 7, 9, 10, 11]), + PB14: (pb14, 14, [1, 3, 5, 7, 9, 12]), + PB15: (pb15, 15, [0, 1, 3, 5, 9, 12]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [8, 10, 12, 14]), + PC1: (pc1, 1, [0, 5, 6, 11]), + PC2: (pc2, 2, [5, 10, 11, 12]), + PC3: (pc3, 3, [5, 10, 11, 12]), + PC4: (pc4, 4, [5, 8, 11, 12]), + PC5: (pc5, 5, [8, 11, 12]), + PC6: (pc6, 6, [2, 3, 5, 8, 12, 13, 14]), + PC7: (pc7, 7, [2, 3, 6, 8, 12, 13, 14]), + PC8: (pc8, 8, [0, 2, 3, 7, 8, 12, 13]), + PC9: (pc9, 9, [0, 2, 3, 4, 5, 7, 9, 12, 13]), + PC10: (pc10, 10, [6, 7, 8, 9, 12, 13, 14]), + PC11: (pc11, 11, [6, 7, 8, 9, 12, 13]), + PC12: (pc12, 12, [0, 6, 7, 8, 12, 13]), + PC13: (pc13, 13, []), + PC14: (pc14, 14, []), + PC15: (pc15, 15, []), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [9, 12]), + PD1: (pd1, 1, [9, 12]), + PD2: (pd2, 2, [0, 2, 8, 12, 13]), + PD3: (pd3, 3, [5, 7, 12, 13, 14]), + PD4: (pd4, 4, [7, 12]), + PD5: (pd5, 5, [7, 12]), + PD6: (pd6, 6, [5, 6, 7, 12, 13, 14]), + PD7: (pd7, 7, [7, 8, 12]), + PD8: (pd8, 8, [7, 8, 12]), + PD9: (pd9, 9, [7, 12]), + PD10: (pd10, 10, [7, 12, 14]), + PD11: (pd11, 11, [4, 7, 9, 10, 12]), + PD12: (pd12, 12, [2, 3, 4, 7, 9, 10, 12]), + PD13: (pd13, 13, [2, 3, 4, 9, 10, 12]), + PD14: (pd14, 14, [2, 8, 12]), + PD15: (pd15, 15, [2, 8, 12]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 3, 8, 10, 12, 13]), + PE1: (pe1, 1, [3, 8, 12, 13]), + PE2: (pe2, 2, [0, 5, 6, 9, 11, 12]), + PE3: (pe3, 3, [0, 6, 12]), + PE4: (pe4, 4, [0, 5, 6, 12, 13, 14]), + PE5: (pe5, 5, [0, 3, 5, 6, 12, 13, 14]), + PE6: (pe6, 6, [0, 1, 3, 5, 6, 10, 12, 13, 14]), + PE7: (pe7, 7, [1, 8, 10, 12]), + PE8: (pe8, 8, [1, 8, 10, 12]), + PE9: (pe9, 9, [1, 8, 10, 12]), + PE10: (pe10, 10, [1, 8, 10, 12]), + PE11: (pe11, 11, [1, 5, 10, 12, 14]), + PE12: (pe12, 12, [1, 5, 10, 12, 14]), + PE13: (pe13, 13, [1, 5, 10, 12, 14]), + PE14: (pe14, 14, [1, 5, 10, 12, 14]), + PE15: (pe15, 15, [1, 12, 14]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 12]), + PF1: (pf1, 1, [4, 12]), + PF2: (pf2, 2, [4, 12]), + PF3: (pf3, 3, [12]), + PF4: (pf4, 4, [12]), + PF5: (pf5, 5, [12]), + PF6: (pf6, 6, [3, 5, 6, 8, 9]), + PF7: (pf7, 7, [3, 5, 6, 8, 9]), + PF8: (pf8, 8, [5, 6, 8, 9, 10]), + PF9: (pf9, 9, [5, 6, 8, 9, 10]), + PF10: (pf10, 10, [13, 14]), + PF11: (pf11, 11, [5, 10, 12, 13]), + PF12: (pf12, 12, [12]), + PF13: (pf13, 13, [4, 12]), + PF14: (pf14, 14, [4, 12]), + PF15: (pf15, 15, [4, 12]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, [ + PG0: (pg0, 0, [12]), + PG1: (pg1, 1, [12]), + PG2: (pg2, 2, [12]), + PG3: (pg3, 3, [12]), + PG4: (pg4, 4, [12]), + PG5: (pg5, 5, [12]), + PG6: (pg6, 6, [13, 14]), + PG7: (pg7, 7, [8, 12, 13, 14]), + PG8: (pg8, 8, [5, 7, 8, 11, 12]), + PG9: (pg9, 9, [7, 8, 9, 10, 12, 13]), + PG10: (pg10, 10, [9, 10, 12, 13, 14]), + PG11: (pg11, 11, [7, 11, 13, 14]), + PG12: (pg12, 12, [3, 5, 7, 8, 9, 12, 14]), + PG13: (pg13, 13, [0, 3, 5, 8, 11, 12, 14]), + PG14: (pg14, 14, [0, 3, 5, 8, 9, 11, 12, 14]), + PG15: (pg15, 15, [8, 12, 13]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, []), + PH1: (ph1, 1, []), + PH2: (ph2, 2, [3, 9, 10, 11, 12, 14]), + PH3: (ph3, 3, [9, 10, 11, 12, 14]), + PH4: (ph4, 4, [4, 10]), + PH5: (ph5, 5, [4, 5, 12]), + PH6: (ph6, 6, [4, 5, 9, 11, 12, 13]), + PH7: (ph7, 7, [4, 5, 11, 12, 13]), + PH8: (ph8, 8, [4, 12, 13, 14]), + PH9: (ph9, 9, [4, 9, 12, 13, 14]), + PH10: (ph10, 10, [2, 4, 12, 13, 14]), + PH11: (ph11, 11, [2, 4, 12, 13, 14]), + PH12: (ph12, 12, [2, 4, 12, 13, 14]), + PH13: (ph13, 13, [3, 9, 12, 14]), + PH14: (ph14, 14, [3, 12, 13, 14]), + PH15: (ph15, 15, [3, 12, 13, 14]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 5, 12, 13, 14]), + PI1: (pi1, 1, [3, 5, 12, 13, 14]), + PI2: (pi2, 2, [3, 5, 12, 13, 14]), + PI3: (pi3, 3, [3, 5, 12, 13]), + PI4: (pi4, 4, [3, 10, 12, 13, 14]), + PI5: (pi5, 5, [3, 10, 12, 13, 14]), + PI6: (pi6, 6, [3, 10, 12, 13, 14]), + PI7: (pi7, 7, [3, 10, 12, 13, 14]), + PI8: (pi8, 8, []), + PI9: (pi9, 9, [9, 12, 14]), + PI10: (pi10, 10, [11, 12, 14]), + PI11: (pi11, 11, [10]), + PI12: (pi12, 12, [14]), + PI13: (pi13, 13, [14]), + PI14: (pi14, 14, [14]), + PI15: (pi15, 15, [14]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOJ, gpioj, PJ, 'J', PJn, [ + PJ0: (pj0, 0, [14]), + PJ1: (pj1, 1, [14]), + PJ2: (pj2, 2, [14]), + PJ3: (pj3, 3, [14]), + PJ4: (pj4, 4, [14]), + PJ5: (pj5, 5, [14]), + PJ6: (pj6, 6, [14]), + PJ7: (pj7, 7, [14]), + PJ8: (pj8, 8, [14]), + PJ9: (pj9, 9, [14]), + PJ10: (pj10, 10, [14]), + PJ11: (pj11, 11, [14]), + PJ12: (pj12, 12, [14]), + PJ13: (pj13, 13, [14]), + PJ14: (pj14, 14, [14]), + PJ15: (pj15, 15, [14]), +]); + +#[cfg(feature = "gpio-f746")] +gpio!(GPIOK, gpiok, PK, 'K', PKn, [ + PK0: (pk0, 0, [14]), + PK1: (pk1, 1, [14]), + PK2: (pk2, 2, [14]), + PK3: (pk3, 3, [14]), + PK4: (pk4, 4, [14]), + PK5: (pk5, 5, [14]), + PK6: (pk6, 6, [14]), + PK7: (pk7, 7, [14]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [1, 2, 3, 7, 8, 10, 11]), + PA1: (pa1, 1, [1, 2, 7, 8, 9, 10, 11, 14]), + PA2: (pa2, 2, [1, 2, 3, 7, 8, 11, 12, 14]), + PA3: (pa3, 3, [1, 2, 3, 7, 9, 10, 11, 14]), + PA4: (pa4, 4, [5, 6, 7, 8, 12, 13, 14]), + PA5: (pa5, 5, [1, 3, 5, 8, 10, 14]), + PA6: (pa6, 6, [1, 2, 3, 5, 8, 9, 12, 13, 14]), + PA7: (pa7, 7, [1, 2, 3, 5, 8, 9, 11, 12]), + PA8: (pa8, 8, [0, 1, 3, 4, 7, 10, 11, 12, 13, 14]), + PA9: (pa9, 9, [1, 4, 5, 7, 13, 14]), + PA10: (pa10, 10, [1, 7, 9, 10, 12, 13, 14]), + PA11: (pa11, 11, [1, 5, 6, 7, 9, 10, 14]), + PA12: (pa12, 12, [1, 5, 6, 7, 8, 9, 10, 14]), + PA13: (pa13, 13, [0], super::Debugger), + PA14: (pa14, 14, [0], super::Debugger), + PA15: (pa15, 15, [0, 1, 4, 5, 6, 7, 8, 11, 12], super::Debugger), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 6, 8, 9, 10, 11, 14]), + PB1: (pb1, 1, [1, 2, 3, 6, 9, 10, 11, 14]), + PB2: (pb2, 2, [6, 7, 9, 10]), + PB3: (pb3, 3, [0, 1, 5, 6, 8, 10, 11, 12], super::Debugger), + PB4: (pb4, 4, [0, 2, 5, 6, 7, 8, 10, 11, 12], super::Debugger), + PB5: (pb5, 5, [1, 2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14]), + PB6: (pb6, 6, [1, 2, 3, 4, 6, 7, 9, 10, 11, 12, 13]), + PB7: (pb7, 7, [2, 4, 6, 7, 11, 12, 13]), + PB8: (pb8, 8, [1, 2, 3, 4, 6, 7, 9, 10, 11, 12, 13, 14]), + PB9: (pb9, 9, [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14]), + PB10: (pb10, 10, [1, 4, 5, 6, 7, 9, 10, 11, 14]), + PB11: (pb11, 11, [1, 4, 6, 7, 10, 11, 13, 14]), + PB12: (pb12, 12, [1, 4, 5, 6, 7, 8, 9, 10, 11, 12]), + PB13: (pb13, 13, [1, 5, 6, 7, 8, 9, 10, 11]), + PB14: (pb14, 14, [1, 3, 4, 5, 6, 7, 8, 9, 10, 12]), + PB15: (pb15, 15, [0, 1, 3, 4, 5, 6, 8, 9, 10, 12]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [3, 6, 8, 10, 12, 14]), + PC1: (pc1, 1, [0, 3, 5, 6, 10, 11, 12]), + PC2: (pc2, 2, [3, 5, 6, 10, 11, 12]), + PC3: (pc3, 3, [3, 5, 10, 11, 12]), + PC4: (pc4, 4, [3, 5, 8, 11, 12]), + PC5: (pc5, 5, [3, 8, 11, 12]), + PC6: (pc6, 6, [2, 3, 5, 7, 8, 9, 10, 12, 13, 14]), + PC7: (pc7, 7, [2, 3, 6, 7, 8, 9, 10, 12, 13, 14]), + PC8: (pc8, 8, [0, 2, 3, 7, 8, 9, 12, 13]), + PC9: (pc9, 9, [0, 2, 3, 4, 5, 7, 9, 10, 12, 13, 14]), + PC10: (pc10, 10, [3, 6, 7, 8, 9, 12, 13, 14]), + PC11: (pc11, 11, [3, 6, 7, 8, 9, 12, 13]), + PC12: (pc12, 12, [0, 6, 7, 8, 12, 13]), + PC13: (pc13, 13, []), + PC14: (pc14, 14, []), + PC15: (pc15, 15, []), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [3, 6, 8, 9, 12]), + PD1: (pd1, 1, [3, 6, 8, 9, 12]), + PD2: (pd2, 2, [0, 2, 8, 12, 13]), + PD3: (pd3, 3, [3, 5, 6, 7, 12, 13, 14]), + PD4: (pd4, 4, [6, 7, 12]), + PD5: (pd5, 5, [7, 12]), + PD6: (pd6, 6, [3, 5, 6, 7, 10, 11, 12, 13, 14]), + PD7: (pd7, 7, [3, 5, 6, 7, 8, 11, 12]), + PD8: (pd8, 8, [3, 7, 8, 12]), + PD9: (pd9, 9, [3, 7, 12]), + PD10: (pd10, 10, [3, 7, 12, 14]), + PD11: (pd11, 11, [4, 7, 9, 10, 12]), + PD12: (pd12, 12, [2, 3, 4, 7, 9, 10, 12]), + PD13: (pd13, 13, [2, 3, 4, 9, 10, 12]), + PD14: (pd14, 14, [2, 8, 12]), + PD15: (pd15, 15, [2, 8, 12]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 3, 8, 10, 12, 13]), + PE1: (pe1, 1, [3, 8, 12, 13]), + PE2: (pe2, 2, [0, 5, 6, 9, 11, 12]), + PE3: (pe3, 3, [0, 6, 12]), + PE4: (pe4, 4, [0, 5, 6, 10, 12, 13, 14]), + PE5: (pe5, 5, [0, 3, 5, 6, 10, 12, 13, 14]), + PE6: (pe6, 6, [0, 1, 3, 5, 6, 10, 12, 13, 14]), + PE7: (pe7, 7, [1, 6, 8, 10, 12]), + PE8: (pe8, 8, [1, 6, 8, 10, 12]), + PE9: (pe9, 9, [1, 6, 8, 10, 12]), + PE10: (pe10, 10, [1, 6, 8, 10, 12]), + PE11: (pe11, 11, [1, 5, 6, 10, 12, 14]), + PE12: (pe12, 12, [1, 5, 6, 10, 12, 14]), + PE13: (pe13, 13, [1, 5, 6, 10, 12, 14]), + PE14: (pe14, 14, [1, 5, 10, 12, 14]), + PE15: (pe15, 15, [1, 12, 14]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOF, gpiof, PF, 'F', PFn, [ + PF0: (pf0, 0, [4, 12]), + PF1: (pf1, 1, [4, 12]), + PF2: (pf2, 2, [4, 12]), + PF3: (pf3, 3, [12]), + PF4: (pf4, 4, [12]), + PF5: (pf5, 5, [12]), + PF6: (pf6, 6, [3, 5, 6, 8, 9]), + PF7: (pf7, 7, [3, 5, 6, 8, 9]), + PF8: (pf8, 8, [5, 6, 8, 9, 10]), + PF9: (pf9, 9, [5, 6, 8, 9, 10]), + PF10: (pf10, 10, [9, 13, 14]), + PF11: (pf11, 11, [5, 10, 12, 13]), + PF12: (pf12, 12, [12]), + PF13: (pf13, 13, [4, 6, 12]), + PF14: (pf14, 14, [4, 6, 12]), + PF15: (pf15, 15, [4, 12]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOG, gpiog, PG, 'G', PGn, [ + PG0: (pg0, 0, [12]), + PG1: (pg1, 1, [12]), + PG2: (pg2, 2, [12]), + PG3: (pg3, 3, [12]), + PG4: (pg4, 4, [12]), + PG5: (pg5, 5, [12]), + PG6: (pg6, 6, [12, 13, 14]), + PG7: (pg7, 7, [6, 8, 12, 13, 14]), + PG8: (pg8, 8, [5, 7, 8, 11, 12, 14]), + PG9: (pg9, 9, [5, 7, 8, 9, 10, 11, 12, 13]), + PG10: (pg10, 10, [5, 9, 10, 11, 12, 13, 14]), + PG11: (pg11, 11, [5, 7, 10, 11, 13, 14]), + PG12: (pg12, 12, [3, 5, 7, 8, 9, 11, 12, 14]), + PG13: (pg13, 13, [0, 3, 5, 8, 11, 12, 14]), + PG14: (pg14, 14, [0, 3, 5, 8, 9, 11, 12, 14]), + PG15: (pg15, 15, [8, 12, 13]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, []), + PH1: (ph1, 1, []), + PH2: (ph2, 2, [3, 9, 10, 11, 12, 14]), + PH3: (ph3, 3, [9, 10, 11, 12, 14]), + PH4: (ph4, 4, [4, 9, 10, 14]), + PH5: (ph5, 5, [4, 5, 12]), + PH6: (ph6, 6, [4, 5, 9, 11, 12, 13]), + PH7: (ph7, 7, [4, 5, 11, 12, 13]), + PH8: (ph8, 8, [4, 12, 13, 14]), + PH9: (ph9, 9, [4, 9, 12, 13, 14]), + PH10: (ph10, 10, [2, 4, 12, 13, 14]), + PH11: (ph11, 11, [2, 4, 12, 13, 14]), + PH12: (ph12, 12, [2, 4, 12, 13, 14]), + PH13: (ph13, 13, [3, 8, 9, 12, 14]), + PH14: (ph14, 14, [3, 8, 9, 12, 13, 14]), + PH15: (ph15, 15, [3, 12, 13, 14]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 5, 12, 13, 14]), + PI1: (pi1, 1, [3, 5, 12, 13, 14]), + PI2: (pi2, 2, [3, 5, 12, 13, 14]), + PI3: (pi3, 3, [3, 5, 12, 13]), + PI4: (pi4, 4, [3, 10, 12, 13, 14]), + PI5: (pi5, 5, [3, 10, 12, 13, 14]), + PI6: (pi6, 6, [3, 10, 12, 13, 14]), + PI7: (pi7, 7, [3, 10, 12, 13, 14]), + PI8: (pi8, 8, []), + PI9: (pi9, 9, [8, 9, 12, 14]), + PI10: (pi10, 10, [11, 12, 14]), + PI11: (pi11, 11, [9, 10]), + PI12: (pi12, 12, [14]), + PI13: (pi13, 13, [14]), + PI14: (pi14, 14, [14]), + PI15: (pi15, 15, [9, 14]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOJ, gpioj, PJ, 'J', PJn, [ + PJ0: (pj0, 0, [9, 14]), + PJ1: (pj1, 1, [14]), + PJ2: (pj2, 2, [13, 14]), + PJ3: (pj3, 3, [14]), + PJ4: (pj4, 4, [14]), + PJ5: (pj5, 5, [14]), + PJ6: (pj6, 6, [14]), + PJ7: (pj7, 7, [14]), + PJ8: (pj8, 8, [14]), + PJ9: (pj9, 9, [14]), + PJ10: (pj10, 10, [14]), + PJ11: (pj11, 11, [14]), + PJ12: (pj12, 12, [9, 14]), + PJ13: (pj13, 13, [9, 14]), + PJ14: (pj14, 14, [14]), + PJ15: (pj15, 15, [14]), +]); + +#[cfg(feature = "gpio-f76x")] +gpio!(GPIOK, gpiok, PK, 'K', PKn, [ + PK0: (pk0, 0, [14]), + PK1: (pk1, 1, [14]), + PK2: (pk2, 2, [14]), + PK3: (pk3, 3, [14]), + PK4: (pk4, 4, [14]), + PK5: (pk5, 5, [14]), + PK6: (pk6, 6, [14]), + PK7: (pk7, 7, [14]), +]); diff --git a/src/i2c.rs b/src/i2c.rs index 73d47b3f..ea4ac6bc 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -82,6 +82,16 @@ pub trait Instance: + Reset + gpio::alt::I2cCommon { + #[doc(hidden)] + #[inline(always)] + fn tx_peri_address() -> u32 { + unsafe { (*Self::ptr()).dr().as_ptr() as u32 } + } + #[doc(hidden)] + #[inline(always)] + fn rx_peri_address() -> u32 { + unsafe { (*Self::ptr()).dr().as_ptr() as u32 } + } } // Implemented by all I2C instances @@ -94,10 +104,16 @@ macro_rules! i2c { } i2c! { pac::I2C1: I2c1 } +#[cfg(feature = "i2c2")] i2c! { pac::I2C2: I2c2 } - #[cfg(feature = "i2c3")] i2c! { pac::I2C3: I2c3 } +#[cfg(feature = "i2c4")] +i2c! { pac::I2C4: I2c4 } +#[cfg(feature = "i2c5")] +i2c! { pac::I2C5: I2c5 } +#[cfg(feature = "i2c6")] +i2c! { pac::I2C6: I2c6 } pub trait I2cExt: Sized + Instance { fn i2c( diff --git a/src/i2c/dma.rs b/src/i2c/dma.rs index 3b441ab5..c5b47e2e 100644 --- a/src/i2c/dma.rs +++ b/src/i2c/dma.rs @@ -902,7 +902,7 @@ pub struct Rx { unsafe impl PeriAddress for Rx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*I2C::ptr()).dr().as_ptr() as u32 } + I2C::rx_peri_address() } type MemSize = u8; @@ -911,7 +911,7 @@ unsafe impl PeriAddress for Rx { unsafe impl PeriAddress for Tx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*I2C::ptr()).dr().as_ptr() as u32 } + I2C::tx_peri_address() } type MemSize = u8; diff --git a/src/i2s.rs b/src/i2s.rs index 48fde593..14bed526 100644 --- a/src/i2s.rs +++ b/src/i2s.rs @@ -282,9 +282,11 @@ i2s!(pac::SPI2, I2s2, i2s2); #[cfg(feature = "spi3")] i2s!(pac::SPI3, I2s3, i2s3); +#[cfg(feature = "f4")] #[cfg(feature = "spi4")] i2s!(pac::SPI4, I2s4, i2s4); +#[cfg(feature = "f4")] #[cfg(feature = "spi5")] i2s!(pac::SPI5, I2s5, i2s5); diff --git a/src/lib.rs b/src/lib.rs index 95c9d484..6cae7fdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,75 +15,101 @@ pub use embedded_hal_02 as hal_02; pub use nb; pub use nb::block; -#[cfg(feature = "stm32f401")] +#[cfg(feature = "svd-f401")] /// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f401 peripherals. pub use stm32f4::stm32f401 as pac; -#[cfg(feature = "stm32f405")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f405 peripherals. +#[cfg(feature = "svd-f405")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f405/f415 peripherals. pub use stm32f4::stm32f405 as pac; -#[cfg(feature = "stm32f407")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f407 peripherals. +#[cfg(feature = "svd-f407")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f407/f417 peripherals. pub use stm32f4::stm32f407 as pac; -#[cfg(feature = "stm32f410")] +#[cfg(feature = "svd-f410")] /// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f410 peripherals. pub use stm32f4::stm32f410 as pac; -#[cfg(feature = "stm32f411")] +#[cfg(feature = "svd-f411")] /// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f411 peripherals. pub use stm32f4::stm32f411 as pac; -#[cfg(feature = "stm32f412")] +#[cfg(feature = "svd-f412")] /// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f412 peripherals. pub use stm32f4::stm32f412 as pac; -#[cfg(feature = "stm32f413")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f413 peripherals. +#[cfg(feature = "svd-f413")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f413/f423 peripherals. pub use stm32f4::stm32f413 as pac; -#[cfg(feature = "stm32f415")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f405 peripherals. -pub use stm32f4::stm32f405 as pac; - -#[cfg(feature = "stm32f417")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f407 peripherals. -pub use stm32f4::stm32f407 as pac; - -#[cfg(feature = "stm32f423")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f413 peripherals. -pub use stm32f4::stm32f413 as pac; - -#[cfg(feature = "stm32f427")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f427 peripherals. +#[cfg(feature = "svd-f427")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f427/f437 peripherals. pub use stm32f4::stm32f427 as pac; -#[cfg(feature = "stm32f429")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f429 peripherals. +#[cfg(feature = "svd-f429")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f429/f439 peripherals. pub use stm32f4::stm32f429 as pac; -#[cfg(feature = "stm32f437")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f427 peripherals. -pub use stm32f4::stm32f427 as pac; - -#[cfg(feature = "stm32f439")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f429 peripherals. -pub use stm32f4::stm32f429 as pac; - -#[cfg(feature = "stm32f446")] +#[cfg(feature = "svd-f446")] /// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f446 peripherals. pub use stm32f4::stm32f446 as pac; -#[cfg(feature = "stm32f469")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f469 peripherals. +#[cfg(feature = "svd-f469")] +/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f469/f479 peripherals. pub use stm32f4::stm32f469 as pac; -#[cfg(feature = "stm32f479")] -/// Re-export of the [svd2rust](https://crates.io/crates/svd2rust) auto-generated API for the stm32f469 peripherals. -pub use stm32f4::stm32f469 as pac; +#[cfg(feature = "svd-f722")] +pub use stm32f7::stm32f722 as pac; + +#[cfg(feature = "svd-f723")] +pub use stm32f7::stm32f723 as pac; + +#[cfg(feature = "svd-f732")] +pub use stm32f7::stm32f732 as pac; + +#[cfg(feature = "svd-f733")] +pub use stm32f7::stm32f733 as pac; + +#[cfg(feature = "svd-f730")] +pub use stm32f7::stm32f730 as pac; + +#[cfg(feature = "svd-f745")] +pub use stm32f7::stm32f745 as pac; + +#[cfg(feature = "svd-f746")] +pub use stm32f7::stm32f746 as pac; + +#[cfg(feature = "svd-f750")] +pub use stm32f7::stm32f750 as pac; + +#[cfg(feature = "svd-f756")] +pub use stm32f7::stm32f756 as pac; + +#[cfg(feature = "svd-f765")] +pub use stm32f7::stm32f765 as pac; + +#[cfg(feature = "svd-f767")] +pub use stm32f7::stm32f767 as pac; + +#[cfg(feature = "svd-f769")] +pub use stm32f7::stm32f769 as pac; + +#[cfg(feature = "svd-f777")] +pub use stm32f7::stm32f777 as pac; + +#[cfg(feature = "svd-f778")] +pub use stm32f7::stm32f778 as pac; + +#[cfg(feature = "svd-f779")] +pub use stm32f7::stm32f779 as pac; + +#[cfg(feature = "f4")] use stm32f4::Periph; +#[cfg(feature = "f7")] +use stm32f7::Periph; + // Enable use of interrupt macro pub use crate::pac::interrupt; @@ -91,13 +117,19 @@ pub mod adc; pub mod bb; #[cfg(all(feature = "can", any(feature = "can1", feature = "can2")))] pub mod can; +#[cfg(feature = "f4")] pub mod crc32; #[cfg(feature = "dac")] pub mod dac; #[cfg(feature = "fmpi2c1")] pub mod fmpi2c; pub mod gpio; +#[cfg(feature = "i2c_v1")] +pub mod i2c; +#[cfg(feature = "i2c_v2")] +#[path = "fmpi2c.rs"] pub mod i2c; +#[cfg(feature = "f4")] pub mod i2s; #[cfg(all(feature = "usb_fs", feature = "otg-fs"))] pub mod otg_fs; @@ -111,6 +143,11 @@ pub mod dma; #[cfg(feature = "dsihost")] pub mod dsi; pub mod dwt; +#[cfg(feature = "f4")] +#[path = "flash/f4.rs"] +pub mod flash; +#[cfg(feature = "f7")] +#[path = "flash/f7.rs"] pub mod flash; #[cfg(any(feature = "fmc", feature = "fsmc"))] #[cfg(feature = "stm32-fmc")] @@ -253,6 +290,7 @@ const fn max_u32(first: u32, second: u32) -> u32 { } } +#[cfg(feature = "f4")] const fn min_u32(first: u32, second: u32) -> u32 { if second < first { second diff --git a/src/ltdc.rs b/src/ltdc.rs index 3bed2623..931374d1 100644 --- a/src/ltdc.rs +++ b/src/ltdc.rs @@ -294,7 +294,10 @@ impl DisplayController { w.pllsain().bits(best_plln as u16); w.pllsair().bits(best_pllr as u8) }); + #[cfg(feature = "f4")] rcc.dckcfgr().modify(|_, w| w.pllsaidivr().set(pllsaidivr)); + #[cfg(feature = "f7")] + rcc.dckcfgr1().modify(|_, w| w.pllsaidivr().set(pllsaidivr)); // Enable PLLSAI and wait for it rcc.cr().modify(|_, w| w.pllsaion().on()); diff --git a/src/otg_fs.rs b/src/otg_fs.rs index 92937e94..075cd121 100644 --- a/src/otg_fs.rs +++ b/src/otg_fs.rs @@ -58,6 +58,7 @@ unsafe impl UsbPeripheral for USB { feature = "gpio-f413", feature = "gpio-f446", feature = "gpio-f469", + feature = "f7", ))] const ENDPOINT_COUNT: usize = 6; diff --git a/src/otg_hs.rs b/src/otg_hs.rs index f62a603b..1fb6c232 100644 --- a/src/otg_hs.rs +++ b/src/otg_hs.rs @@ -12,6 +12,8 @@ use crate::gpio::alt::otg_hs as alt; use crate::rcc::{Clocks, Enable, Reset}; use fugit::HertzU32 as Hertz; +#[cfg(feature = "usb_hs_phy")] +use synopsys_usb_otg::PhyType; pub use synopsys_usb_otg::UsbBus; use synopsys_usb_otg::UsbPeripheral; @@ -22,9 +24,16 @@ pub struct USB { pub pin_dm: alt::Dm, pub pin_dp: alt::Dp, pub hclk: Hertz, + #[cfg(feature = "usb_hs_phy")] + usb_phy: Option, + #[cfg(feature = "usb_hs_phy")] + pub hse: Hertz, } impl USB { + /// Construct a USB peripheral wrapper. + /// + /// Call `UsbBus::new` to construct and initialize the USB peripheral driver. pub fn new( periphs: (pac::OTG_HS_GLOBAL, pac::OTG_HS_DEVICE, pac::OTG_HS_PWRCLK), pins: (impl Into, impl Into), @@ -34,9 +43,38 @@ impl USB { usb_global: periphs.0, usb_device: periphs.1, usb_pwrclk: periphs.2, + #[cfg(feature = "usb_hs_phy")] + usb_phy: None, pin_dm: pins.0.into(), pin_dp: pins.1.into(), hclk: clocks.hclk(), + #[cfg(feature = "usb_hs_phy")] + hse: clocks.hse().unwrap_or_else(|| Hertz::Hz(0)), + } + } + + #[cfg(feature = "usb_hs_phy")] + /// Construct a USB peripheral wrapper with internal HighSpeed PHY. + /// + /// Call `UsbBus::new` to construct and initialize the USB peripheral driver. + pub fn new_with_internal_hs_phy( + usb_global: pac::OTG_HS_GLOBAL, + usb_device: pac::OTG_HS_DEVICE, + usb_pwrclk: pac::OTG_HS_PWRCLK, + usb_phy: pac::USBPHYC, + pins: (impl Into, impl Into), + clocks: &Clocks, + ) -> Self { + use crate::rcc::BusClock; + Self { + usb_global, + usb_device, + usb_pwrclk, + usb_phy: Some(usb_phy), + pin_dm: pins.0.into(), + pin_dp: pins.1.into(), + hclk: pac::OTG_HS_GLOBAL::clock(clocks), + hse: clocks.hse().expect("HSE should be enabled"), } } } @@ -51,16 +89,23 @@ unsafe impl UsbPeripheral for USB { #[cfg(any(feature = "gpio-f417", feature = "gpio-f427"))] const ENDPOINT_COUNT: usize = 6; - #[cfg(any(feature = "gpio-f446", feature = "gpio-f469"))] + #[cfg(any(feature = "gpio-f446", feature = "gpio-f469", feature = "f7"))] const ENDPOINT_COUNT: usize = 9; fn enable() { - cortex_m::interrupt::free(|_| { - unsafe { - // Enable USB peripheral - pac::OTG_HS_GLOBAL::enable_unchecked(); - // Reset USB peripheral - pac::OTG_HS_GLOBAL::reset_unchecked(); + cortex_m::interrupt::free(|_| unsafe { + // Enable USB peripheral + pac::OTG_HS_GLOBAL::enable_unchecked(); + // Reset USB peripheral + pac::OTG_HS_GLOBAL::reset_unchecked(); + + #[cfg(feature = "usb_hs_phy")] + { + // Enable and reset HS PHY + let rcc = &*pac::RCC::ptr(); + rcc.ahb1enr().modify(|_, w| w.otghsulpien().enabled()); + pac::USBPHYC::enable_unchecked(); + pac::USBPHYC::reset_unchecked(); } }); } @@ -68,6 +113,59 @@ unsafe impl UsbPeripheral for USB { fn ahb_frequency_hz(&self) -> u32 { self.hclk.raw() } + + #[cfg(feature = "usb_hs_phy")] + #[inline(always)] + fn phy_type(&self) -> PhyType { + if self.usb_phy.is_some() { + PhyType::InternalHighSpeed + } else { + PhyType::InternalFullSpeed + } + } + + #[cfg(feature = "usb_hs_phy")] + // Setup LDO and PLL + fn setup_internal_hs_phy(&self) { + let phy = if let Some(phy) = self.usb_phy.as_ref() { + phy + } else { + // This should never happen as this function is only called when + // phy_type() is PhyType::InternalHighSpeed and it's possible only + // when self.usb_phy is not None + unreachable!() + }; + + // Calculate PLL1SEL + let pll1sel = match self.hse.raw() { + 12_000_000 => 0b000, + 12_500_000 => 0b001, + 16_000_000 => 0b011, + 24_000_000 => 0b100, + 25_000_000 => 0b101, + _ => panic!("HSE frequency is invalid for USBPHYC"), + }; + + // Turn on LDO + // For some reason setting the bit enables the LDO + phy.ldo().modify(|_, w| w.ldo_disable().set_bit()); + + // Busy wait until ldo_status becomes true + // Notice, this may hang + while phy.ldo().read().ldo_status().bit_is_clear() {} + + // Setup PLL + // This disables the the pll1 during tuning + phy.pll1().write(|w| unsafe { w.pll1sel().bits(pll1sel) }); + + phy.tune() + .modify(|r, w| unsafe { w.bits(r.bits() | 0xF13) }); + + phy.pll1().modify(|_, w| w.pll1en().set_bit()); + + // 2ms Delay required to get internal phy clock stable + cortex_m::asm::delay(432000); + } } pub type UsbBusType = UsbBus; diff --git a/src/pacext.rs b/src/pacext.rs index 33b39106..cf767b3e 100644 --- a/src/pacext.rs +++ b/src/pacext.rs @@ -1,7 +1,15 @@ +#[cfg(feature = "f4")] use stm32f4::{Readable, Reg, RegisterSpec, Resettable, Writable, R, W}; +#[cfg(feature = "f4")] +#[path = "./pacext/uart_v2.rs"] pub mod uart; +#[cfg(feature = "f7")] +#[path = "./pacext/uart_v3.rs"] +pub mod uart; + +#[cfg(feature = "f4")] macro_rules! wrap_r { (pub trait $TrR:ident { $(fn $f:ident(&self $(, $n:ident: u8)?) -> $fr:path;)* @@ -19,8 +27,10 @@ macro_rules! wrap_r { } }; } +#[cfg(feature = "f4")] pub(crate) use wrap_r; +#[cfg(feature = "f4")] macro_rules! wrap_w { (pub trait $TrR:ident { $(fn $f:ident(&mut self $(, $n:ident: u8)?) -> $fr:path;)* @@ -39,6 +49,7 @@ macro_rules! wrap_w { } }; } +#[cfg(feature = "f4")] pub(crate) use wrap_w; macro_rules! impl_reg { @@ -53,6 +64,7 @@ macro_rules! impl_reg { } pub(crate) use impl_reg; +#[cfg(feature = "f4")] macro_rules! impl_read { ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { $( @@ -63,8 +75,10 @@ macro_rules! impl_read { )* }; } +#[cfg(feature = "f4")] pub(crate) use impl_read; +#[cfg(feature = "f4")] macro_rules! impl_write { ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { $( @@ -75,4 +89,5 @@ macro_rules! impl_write { )* }; } +#[cfg(feature = "f4")] pub(crate) use impl_write; diff --git a/src/pacext/uart.rs b/src/pacext/uart_v2.rs similarity index 100% rename from src/pacext/uart.rs rename to src/pacext/uart_v2.rs diff --git a/src/pacext/uart_v3.rs b/src/pacext/uart_v3.rs new file mode 100644 index 00000000..7b4d069c --- /dev/null +++ b/src/pacext/uart_v3.rs @@ -0,0 +1,37 @@ +use crate::Sealed; + +use super::*; +use crate::pac::usart1; + +pub trait UartRB: Sealed { + fn cr1(&self) -> &usart1::CR1; + fn rdr(&self) -> &usart1::RDR; + fn tdr(&self) -> &usart1::TDR; + fn brr(&self) -> &usart1::BRR; + fn icr(&self) -> &usart1::ICR; + fn isr(&self) -> &usart1::ISR; + fn cr2(&self) -> &usart1::CR2; + fn cr3(&self) -> &usart1::CR3; + fn gtpr(&self) -> &usart1::GTPR; +} + +macro_rules! impl_ext { + ($(#[$attr:meta])* $uart:ident) => { + impl Sealed for $uart::RegisterBlock {} + impl UartRB for $uart::RegisterBlock { + impl_reg! { + cr1 -> &usart1::CR1; + rdr -> &usart1::RDR; + tdr -> &usart1::TDR; + brr -> &usart1::BRR; + icr -> &usart1::ICR; + isr -> &usart1::ISR; + cr2 -> &usart1::CR2; + cr3 -> &usart1::CR3; + gtpr -> &usart1::GTPR; + } + } + }; +} + +impl_ext!(usart1); diff --git a/src/prelude.rs b/src/prelude.rs index d3722cca..cf60b466 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -60,11 +60,16 @@ pub use crate::fmpi2c::I2cExt as _; pub use crate::gpio::outport::OutPort as _; pub use crate::gpio::ExtiPin as _stm32f4xx_hal_gpio_ExtiPin; pub use crate::gpio::GpioExt as _stm32f4xx_hal_gpio_GpioExt; +#[cfg(feature = "f4")] pub use crate::i2c::dma::I2CMasterHandleIT as _stm32f4xx_hal_i2c_dma_I2CMasterHandleIT; +#[cfg(feature = "f4")] pub use crate::i2c::dma::I2CMasterReadDMA as _stm32f4xx_hal_i2c_dma_I2CMasterReadDMA; +#[cfg(feature = "f4")] pub use crate::i2c::dma::I2CMasterWriteDMA as _stm32f4xx_hal_i2c_dma_I2CMasterWriteDMA; +#[cfg(feature = "f4")] pub use crate::i2c::dma::I2CMasterWriteReadDMA as _stm32f4xx_hal_i2c_dma_I2CMasterWriteReadDMA; pub use crate::i2c::I2cExt as _stm32f4xx_hal_i2c_I2cExt; +#[cfg(feature = "f4")] pub use crate::i2s::I2sExt as _stm32f4xx_hal_i2s_I2sExt; pub use crate::qei::QeiExt as _stm32f4xx_hal_QeiExt; pub use crate::rcc::RccExt as _stm32f4xx_hal_rcc_RccExt; diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs new file mode 100644 index 00000000..d9be56eb --- /dev/null +++ b/src/rcc/enable.rs @@ -0,0 +1,396 @@ +use super::*; + +macro_rules! bus { + ($($PER:ident => ($busX:ty, $bit:literal, $($en:ident)?, $($lpen:ident)?, $($rst:ident)?),)+) => { + $( + impl RccBus for crate::pac::$PER { + type Bus = $busX; + } + $(bus_enable!($PER => $bit, $en);)? + $(bus_lpenable!($PER => $bit, $lpen);)? + $(bus_reset!($PER => $bit, $rst);)? + )+ + } +} +use bus; + +macro_rules! bus_enable { + ($PER:ident => $bit:literal, $en:ident) => { + impl $crate::rcc::Enable for crate::pac::$PER { + #[inline(always)] + fn enable(rcc: &mut RCC) { + let reg = Self::Bus::enr(rcc); + #[cfg(feature = "bb")] + unsafe { + $crate::bb::set(reg, $bit); + } + #[cfg(not(feature = "bb"))] + reg.modify(|_, w| w.$en().set_bit()); + // Stall the pipeline to work around erratum 2.1.13 (DM00037591) + cortex_m::asm::dsb(); + } + #[inline(always)] + fn disable(rcc: &mut RCC) { + let reg = Self::Bus::enr(rcc); + #[cfg(feature = "bb")] + unsafe { + $crate::bb::clear(reg, $bit); + } + #[cfg(not(feature = "bb"))] + reg.modify(|_, w| w.$en().clear_bit()); + } + #[inline(always)] + fn is_enabled() -> bool { + let reg = Self::Bus::enr(unsafe { &*RCC::ptr() }); + #[cfg(feature = "bb")] + { + (reg.read().bits() >> $bit) & 0x1 != 0 + } + #[cfg(not(feature = "bb"))] + { + reg.read().$en().bit_is_set() + } + } + } + }; +} +use bus_enable; + +macro_rules! bus_lpenable { + ($PER:ident => $bit:literal, $lpen:ident) => { + impl $crate::rcc::LPEnable for crate::pac::$PER { + #[inline(always)] + fn enable_in_low_power(rcc: &mut RCC) { + let reg = Self::Bus::lpenr(rcc); + #[cfg(feature = "bb")] + unsafe { + $crate::bb::set(reg, $bit); + } + #[cfg(not(feature = "bb"))] + reg.modify(|_, w| w.$lpen().set_bit()); + // Stall the pipeline to work around erratum 2.1.13 (DM00037591) + cortex_m::asm::dsb(); + } + #[inline(always)] + fn disable_in_low_power(rcc: &mut RCC) { + let reg = Self::Bus::lpenr(rcc); + #[cfg(feature = "bb")] + unsafe { + $crate::bb::clear(reg, $bit); + } + #[cfg(not(feature = "bb"))] + reg.modify(|_, w| w.$lpen().clear_bit()); + } + #[inline(always)] + fn is_enabled_in_low_power() -> bool { + let rcc = RCC::ptr(); + let reg = Self::Bus::lpenr(unsafe { &*rcc }); + #[cfg(feature = "bb")] + { + (reg.read().bits() >> $bit) & 0x1 != 0 + } + #[cfg(not(feature = "bb"))] + { + reg.read().$lpen().bit_is_set() + } + } + } + }; +} +use bus_lpenable; + +macro_rules! bus_reset { + ($PER:ident => $bit:literal, $rst:ident) => { + impl $crate::rcc::Reset for crate::pac::$PER { + #[inline(always)] + fn reset(rcc: &mut RCC) { + let reg = Self::Bus::rstr(rcc); + #[cfg(feature = "bb")] + unsafe { + $crate::bb::set(reg, $bit); + $crate::bb::clear(reg, $bit); + } + #[cfg(not(feature = "bb"))] + { + let bits = reg.modify(|_, w| w.$rst().set_bit()); + reg.write(|w| unsafe { w.bits(bits).$rst().clear_bit() }); + } + } + } + }; +} +use bus_reset; + +bus! { + GPIOA => (AHB1, 0, gpioaen, gpioalpen, gpioarst), + GPIOB => (AHB1, 1, gpioben, gpioblpen, gpiobrst), +} +#[cfg(feature = "gpioc")] +bus! { GPIOC => (AHB1, 2, gpiocen, gpioclpen, gpiocrst),} +#[cfg(feature = "gpiod")] +bus! { GPIOD => (AHB1, 3, gpioden, gpiodlpen, gpiodrst),} +#[cfg(feature = "gpioe")] +bus! { GPIOE => (AHB1, 4, gpioeen, gpioelpen, gpioerst),} +#[cfg(feature = "gpiof")] +bus! { GPIOF => (AHB1, 5, gpiofen, gpioflpen, gpiofrst),} +#[cfg(feature = "gpiog")] +bus! { GPIOG => (AHB1, 6, gpiogen, gpioglpen, gpiogrst),} +#[cfg(feature = "gpioh")] +bus! { GPIOH => (AHB1, 7, gpiohen, gpiohlpen, gpiohrst),} +#[cfg(feature = "gpioi")] +bus! { GPIOI => (AHB1, 8, gpioien, gpioilpen, gpioirst),} +#[cfg(feature = "gpioj")] +bus! { GPIOJ => (AHB1, 9, gpiojen, gpiojlpen, gpiojrst),} +#[cfg(feature = "gpiok")] +bus! { GPIOK => (AHB1, 10, gpioken, gpioklpen, gpiokrst),} + +bus! { + CRC => (AHB1, 12, crcen, crclpen, crcrst), + DMA1 => (AHB1, 21, dma1en, dma1lpen, dma1rst), + DMA2 => (AHB1, 22, dma2en, dma2lpen, dma2rst), +} + +#[cfg(feature = "dma2d")] +bus! { DMA2D => (AHB1, 23, dma2den, dma2dlpen, dma2drst),} + +#[cfg(feature = "eth")] +bus! { ETHERNET_MAC => (AHB1, 25, ethmacen, ethmaclpen, ethmacrst),} + +#[cfg(feature = "otg-hs")] +bus! { OTG_HS_GLOBAL => (AHB1, 29, otghsen, otghslpen, otghsrst),} + +#[cfg(feature = "dcmi")] +bus! { DCMI => (AHB2, 0, dcmien, dcmilpen, dcmirst),} + +#[cfg(feature = "jpeg")] +bus! { JPEG => (AHB2, 1, jpegen, jpeglpen,),} + +#[cfg(feature = "f4")] +#[cfg(feature = "aes")] +bus! { AES => (AHB2, 4, crypen, , cryprst),} + +#[cfg(not(feature = "f4"))] +#[cfg(feature = "aes")] +bus! { AES => (AHB2, 4, aesen, aeslpen, aesrst),} + +#[cfg(feature = "cryp")] +bus! { CRYP => (AHB2, 4, crypen, cryplpen, cryprst),} + +#[cfg(feature = "hash")] +bus! { HASH => (AHB2, 5, hashen, hashlpen,),} + +#[cfg(feature = "rng")] +bus! { RNG => (AHB2, 6, rngen, rnglpen, rngrst),} + +#[cfg(feature = "otg-fs")] +bus! { OTG_FS_GLOBAL => (AHB2, 7, otgfsen, otgfslpen, otgfsrst),} + +#[cfg(feature = "fmc")] +bus! { FMC => (AHB3, 0, fmcen, fmclpen, fmcrst),} + +#[cfg(feature = "fsmc")] +#[cfg(feature = "svd-f427")] +bus! { FSMC => (AHB3, 0, fmcen, fmclpen, fmcrst),} + +#[cfg(feature = "fsmc")] +#[cfg(not(feature = "svd-f427"))] +bus! { FSMC => (AHB3, 0, fsmcen, fsmclpen, fsmcrst),} + +#[cfg(feature = "quadspi")] +bus! { QUADSPI => (AHB3, 1, qspien, , qspirst),} + +#[cfg(feature = "tim2")] +bus! { TIM2 => (APB1, 0, tim2en, tim2lpen, tim2rst),} +#[cfg(feature = "tim3")] +bus! { TIM3 => (APB1, 1, tim3en, tim3lpen, tim3rst),} +#[cfg(feature = "tim4")] +bus! { TIM4 => (APB1, 2, tim4en, tim4lpen, tim4rst),} +#[cfg(feature = "tim5")] +bus! { TIM5 => (APB1, 3, tim5en, tim5lpen, tim5rst),} +#[cfg(feature = "tim6")] +bus! { TIM6 => (APB1, 4, tim6en, tim6lpen, tim6rst),} +#[cfg(feature = "tim7")] +bus! { TIM7 => (APB1, 5, tim7en, tim7lpen, tim7rst),} +#[cfg(feature = "tim12")] +bus! { TIM12 => (APB1, 6, tim12en, tim12lpen, tim12rst),} +#[cfg(feature = "tim13")] +bus! { TIM13 => (APB1, 7, tim13en, tim13lpen, tim13rst),} +#[cfg(feature = "tim14")] +bus! { TIM14 => (APB1, 8, tim14en, tim14lpen, tim14rst),} + +#[cfg(feature = "lptim1")] +#[cfg(not(feature = "svd-f413"))] +bus! { LPTIM1 => (APB1, 9, lptim1en, lptim1lpen, lptim1rst),} +#[cfg(feature = "lptim1")] +#[cfg(feature = "svd-f413")] +bus! { LPTIM => (APB1, 9, lptimer1en, lptimer1lpen, lptimer1rst),} + +bus! { WWDG => (APB1, 11, wwdgen, wwdglpen, wwdgrst),} + +#[cfg(feature = "spi2")] +bus! { SPI2 => (APB1, 14, spi2en, spi2lpen, spi2rst),} +#[cfg(feature = "spi3")] +bus! { SPI3 => (APB1, 15, spi3en, spi3lpen, spi3rst),} + +#[cfg(feature = "spdifrx")] +bus! { SPDIFRX => (APB1, 16, spdifrxen, spdifrxlpen, spdifrxrst),} + +#[cfg(feature = "usart2")] +bus! { USART2 => (APB1, 17, usart2en, usart2lpen, usart2rst),} +#[cfg(feature = "usart3")] +bus! { USART3 => (APB1, 18, usart3en, usart3lpen, usart3rst),} + +#[cfg(feature = "uart4")] +bus! { UART4 => (APB1, 19, uart4en, uart4lpen, uart4rst),} +#[cfg(feature = "uart5")] +bus! { UART5 => (APB1, 20, uart5en, uart5lpen, uart5rst),} + +bus! { I2C1 => (APB1, 21, i2c1en, i2c1lpen, i2c1rst),} +#[cfg(feature = "i2c2")] +bus! { I2C2 => (APB1, 22, i2c2en, i2c2lpen, i2c2rst),} +#[cfg(feature = "i2c3")] +bus! { I2C3 => (APB1, 23, i2c3en, i2c3lpen, i2c3rst),} +#[cfg(feature = "i2c4")] +bus! { I2C4 => (APB1, 24, i2c4en, i2c4lpen, i2c4rst),} +#[cfg(feature = "fmpi2c1")] +#[cfg(not(feature = "svd-f412"))] +bus! { FMPI2C1 => (APB1, 24, fmpi2c1en, fmpi2c1lpen, fmpi2c1rst),} +#[cfg(feature = "fmpi2c1")] +#[cfg(feature = "svd-f412")] +bus! { FMPI2C1 => (APB1, 24, i2c4en, i2c4lpen, i2c4rst),} + +#[cfg(feature = "can1")] +bus! { CAN1 => (APB1, 25, can1en, can1lpen, can1rst),} +#[cfg(feature = "can2")] +bus! { CAN2 => (APB1, 26, can2en, can2lpen, can2rst),} + +#[cfg(feature = "f4")] +#[cfg(feature = "can3")] +bus! { CAN3 => (APB1, 27, can3en, can3lpen, can3rst),} + +#[cfg(feature = "f7")] +#[cfg(feature = "can3")] +bus! { CAN3 => (APB1, 13, can3en, can3lpen, can3rst),} + +#[cfg(feature = "f4")] +#[cfg(feature = "cec")] +bus! { HDMP_CEC => (APB1, 27, cecen, ceclpen, cecrst),} + +#[cfg(feature = "f7")] +#[cfg(feature = "cec")] +bus! { CEC => (APB1, 27, cecen, ceclpen, cecrst),} + +bus! { PWR => (APB1, 28, pwren, pwrlpen, pwrrst),} + +#[cfg(feature = "dac")] +bus! { DAC => (APB1, 29, dacen, daclpen, dacrst),} + +#[cfg(feature = "uart7")] +bus! {UART7 => (APB1, 30, uart7en, uart7lpen, uart7rst),} +#[cfg(feature = "uart8")] +bus! {UART8 => (APB1, 31, uart8en, uart8lpen, uart8rst),} + +#[cfg(feature = "tim1")] +bus! { TIM1 => (APB2, 0, tim1en, tim1lpen, tim1rst),} +#[cfg(feature = "tim8")] +bus! {TIM8 => (APB2, 1, tim8en, tim8lpen, tim8rst),} + +#[cfg(feature = "usart1")] +bus! { USART1 => (APB2, 4, usart1en, usart1lpen, usart1rst),} +#[cfg(feature = "usart6")] +bus! { USART6 => (APB2, 5, usart6en, usart6lpen, usart6rst),} +#[cfg(feature = "uart9")] +bus! { UART9 => (APB2, 6, uart9en, uart9lpen, uart9rst),} +#[cfg(feature = "uart10")] +bus! { UART10 => (APB2, 7, uart10en, uart10lpen, uart10rst),} + +#[cfg(feature = "sdmmc2")] +bus! { SDMMC2 => (APB2, 7, sdmmc2en, sdmmc2lpen, sdmmc2rst),} + +bus! { ADC1 => (APB2, 8, adc1en, adc1lpen, adcrst),} + +#[cfg(feature = "adc2")] +bus! { ADC2 => (APB2, 9, adc2en, adc2lpen, ),} +#[cfg(feature = "adc2")] +bus_reset!(ADC2 => 8, adcrst); + +#[cfg(feature = "adc3")] +bus! { ADC3 => (APB2, 10, adc3en, adc3lpen, ),} +#[cfg(feature = "adc3")] +bus_reset!(ADC3 => 8, adcrst); + +#[cfg(feature = "sdio")] +bus! { SDIO => (APB2, 11, sdioen, sdiolpen, sdiorst),} +#[cfg(feature = "sdmmc1")] +bus! { SDMMC1 => (APB2, 11, sdmmc1en, sdmmc1lpen, sdmmc1rst),} + +#[cfg(feature = "spi1")] +bus! { SPI1 => (APB2, 12, spi1en, spi1lpen, spi1rst),} +#[cfg(feature = "spi4")] +bus! { SPI4 => (APB2, 13, spi4en, spi4lpen, spi4rst),} + +#[cfg(feature = "sys")] +bus! { SYSCFG => (APB2, 14, syscfgen, syscfglpen, syscfgrst),} + +#[cfg(feature = "tim9")] +bus! {TIM9 => (APB2, 16, tim9en, tim9lpen, tim9rst),} +#[cfg(feature = "tim10")] +bus! { TIM10 => (APB2, 17, tim10en, tim10lpen, tim10rst),} +#[cfg(feature = "tim11")] +bus! { TIM11 => (APB2, 18, tim11en, tim11lpen, tim11rst),} + +#[cfg(feature = "spi5")] +bus! { SPI5 => (APB2, 20, spi5en, spi5lpen, spi5rst),} +#[cfg(feature = "spi6")] +bus! { SPI6 => (APB2, 21, spi6en, spi6lpen, spi6rst),} + +#[cfg(any( + feature = "gpio-f413", + feature = "gpio-f469", + feature = "stm32f429", + feature = "stm32f439" +))] +#[cfg(feature = "sai1")] +bus! { + SAI => (APB2, 22, sai1en, sai1lpen, sai1rst), +} + +#[cfg(not(any( + feature = "gpio-f413", + feature = "gpio-f469", + feature = "stm32f429", + feature = "stm32f439" +)))] +#[cfg(feature = "sai1")] +bus! { + SAI1 => (APB2, 22, sai1en, sai1lpen, sai1rst), +} + +#[cfg(feature = "sai2")] +bus! { +SAI2 => (APB2, 23, sai2en, sai2lpen, sai2rst),} + +#[cfg(feature = "gpio-f412")] +#[cfg(feature = "dfsdm1")] +bus! { DFSDM => (APB2, 24, dfsdmen, dfsdmlpen, dfsdmrst),} +#[cfg(feature = "gpio-f413")] +#[cfg(feature = "dfsdm1")] +bus! { DFSDM1 => (APB2, 24, dfsdmen, dfsdmlpen, dfsdmrst),} +#[cfg(feature = "f4")] +#[cfg(feature = "dfsdm2")] +bus! { DFSDM2 => (APB2, 25, dfsdmen, dfsdmlpen, dfsdmrst),} + +#[cfg(feature = "ltdc")] +bus! { LTDC => (APB2, 26, ltdcen, ltdclpen, ltdcrst),} + +#[cfg(feature = "dsihost")] +bus! { DSI => (APB2, 27, dsien, dsilpen, dsirst),} + +#[cfg(feature = "f7")] +#[cfg(feature = "dfsdm1")] +bus! { DFSDM => (APB2, 29, dfsdm1en, dfsdm1lpen, dfsdm1rst),} + +#[cfg(feature = "mdios")] +bus! { MDIOS => (APB2, 30, mdioen, mdiolpen, mdiorst),} +#[cfg(feature = "svd-f730")] +bus! { USBPHYC => (APB2, 31, usbphycen,, usbphycrst),} diff --git a/src/rcc/f4/enable.rs b/src/rcc/f4/enable.rs deleted file mode 100644 index 433f3cc8..00000000 --- a/src/rcc/f4/enable.rs +++ /dev/null @@ -1,359 +0,0 @@ -use super::*; -use crate::bb; - -macro_rules! bus_enable { - ($PER:ident => $bit:literal) => { - impl Enable for crate::pac::$PER { - #[inline(always)] - fn enable(rcc: &RccRB) { - unsafe { - bb::set(Self::Bus::enr(rcc), $bit); - } - // Stall the pipeline to work around erratum 2.1.13 (DM00037591) - cortex_m::asm::dsb(); - } - #[inline(always)] - fn disable(rcc: &RccRB) { - unsafe { - bb::clear(Self::Bus::enr(rcc), $bit); - } - } - #[inline(always)] - fn is_enabled() -> bool { - let rcc = pac::RCC::ptr(); - (Self::Bus::enr(unsafe { &*rcc }).read().bits() >> $bit) & 0x1 != 0 - } - } - }; -} -macro_rules! bus_lpenable { - ($PER:ident => $bit:literal) => { - impl LPEnable for crate::pac::$PER { - #[inline(always)] - fn enable_in_low_power(rcc: &RccRB) { - unsafe { - bb::set(Self::Bus::lpenr(rcc), $bit); - } - // Stall the pipeline to work around erratum 2.1.13 (DM00037591) - cortex_m::asm::dsb(); - } - #[inline(always)] - fn disable_in_low_power(rcc: &RccRB) { - unsafe { - bb::clear(Self::Bus::lpenr(rcc), $bit); - } - } - #[inline(always)] - fn is_enabled_in_low_power() -> bool { - let rcc = pac::RCC::ptr(); - (Self::Bus::lpenr(unsafe { &*rcc }).read().bits() >> $bit) & 0x1 != 0 - } - } - }; -} -macro_rules! bus_reset { - ($PER:ident => $bit:literal) => { - impl Reset for crate::pac::$PER { - #[inline(always)] - fn reset(rcc: &RccRB) { - unsafe { - bb::set(Self::Bus::rstr(rcc), $bit); - bb::clear(Self::Bus::rstr(rcc), $bit); - } - } - } - }; -} - -macro_rules! bus { - ($($PER:ident => ($busX:ty, $bit:literal),)+) => { - $( - impl RccBus for crate::pac::$PER { - type Bus = $busX; - } - bus_enable!($PER => $bit); - bus_lpenable!($PER => $bit); - bus_reset!($PER => $bit); - )+ - } -} - -#[cfg(feature = "quadspi")] -impl RccBus for crate::pac::QUADSPI { - type Bus = AHB3; -} - -#[cfg(feature = "quadspi")] -bus_enable! { QUADSPI => 1 } -#[cfg(feature = "quadspi")] -bus_reset! { QUADSPI => 1 } - -bus! { - CRC => (AHB1, 12), - DMA1 => (AHB1, 21), - DMA2 => (AHB1, 22), -} - -bus! { - GPIOA => (AHB1, 0), - GPIOB => (AHB1, 1), - GPIOC => (AHB1, 2), - GPIOH => (AHB1, 7), -} - -#[cfg(any(feature = "gpiod", feature = "gpioe"))] -bus! { - GPIOD => (AHB1, 3), - GPIOE => (AHB1, 4), -} -#[cfg(any(feature = "gpiof", feature = "gpiog"))] -bus! { - GPIOF => (AHB1, 5), - GPIOG => (AHB1, 6), -} - -#[cfg(feature = "gpioi")] -bus! { - GPIOI => (AHB1, 8), -} - -#[cfg(any(feature = "gpioj", feature = "gpiok"))] -bus! { - GPIOJ => (AHB1, 9), - GPIOK => (AHB1, 10), -} - -#[cfg(feature = "rng")] -bus! { - RNG => (AHB2, 6), -} - -#[cfg(feature = "otg-fs")] -bus! { - OTG_FS_GLOBAL => (AHB2, 7), -} - -#[cfg(feature = "otg-hs")] -bus! { - OTG_HS_GLOBAL => (AHB1, 29), -} - -#[cfg(feature = "fmc")] -bus! { - FMC => (AHB3, 0), -} - -// TODO: fix absent ahb3lpenr -#[cfg(feature = "fsmc")] -impl RccBus for crate::pac::FSMC { - type Bus = AHB3; -} -#[cfg(feature = "fsmc")] -bus_enable!(FSMC => 0); -#[cfg(feature = "fsmc")] -bus_reset!(FSMC => 0); - -bus! { - PWR => (APB1, 28), -} - -bus! { - SPI1 => (APB2, 12), - SPI2 => (APB1, 14), -} -#[cfg(feature = "spi3")] -bus! { - SPI3 => (APB1, 15), -} - -#[cfg(feature = "spi4")] -bus! { - SPI4 => (APB2, 13), -} - -#[cfg(feature = "spi5")] -bus! { - SPI5 => (APB2, 20), -} - -#[cfg(feature = "spi6")] -bus! { - SPI6 => (APB2, 21), -} - -bus! { - I2C1 => (APB1, 21), - I2C2 => (APB1, 22), -} -#[cfg(feature = "i2c3")] -bus! { - I2C3 => (APB1, 23), -} -#[cfg(feature = "fmpi2c1")] -bus! { - FMPI2C1 => (APB1, 24), -} - -bus! { - USART1 => (APB2, 4), - USART2 => (APB1, 17), - USART6 => (APB2, 5), -} -#[cfg(feature = "usart3")] -bus! { - USART3 => (APB1, 18), -} - -#[cfg(any(feature = "uart4", feature = "uart5"))] -bus! { - UART4 => (APB1, 19), - UART5 => (APB1, 20), -} - -#[cfg(any(feature = "uart7", feature = "uart8"))] -bus! { - UART7 => (APB1, 30), - UART8 => (APB1, 31), -} -#[cfg(any(feature = "uart9", feature = "uart10"))] -bus! { - UART9 => (APB2, 6), - UART10 => (APB2, 7), -} - -#[cfg(any(feature = "can1", feature = "can2"))] -bus! { - CAN1 => (APB1, 25), - CAN2 => (APB1, 26), -} - -#[cfg(feature = "can3")] -bus! { - CAN3 => (APB1, 27), -} - -#[cfg(feature = "dac")] -bus! { - DAC => (APB1, 29), -} - -bus! { - SYSCFG => (APB2, 14), -} - -bus! { - ADC1 => (APB2, 8), -} - -#[cfg(feature = "adc2")] -impl RccBus for crate::pac::ADC2 { - type Bus = APB2; -} -#[cfg(feature = "adc2")] -bus_enable!(ADC2 => 9); -#[cfg(feature = "adc2")] -bus_lpenable!(ADC2 => 9); -#[cfg(feature = "adc2")] -bus_reset!(ADC2 => 8); - -#[cfg(feature = "adc3")] -impl RccBus for crate::pac::ADC3 { - type Bus = APB2; -} -#[cfg(feature = "adc3")] -bus_enable!(ADC3 => 10); -#[cfg(feature = "adc3")] -bus_lpenable!(ADC3 => 10); -#[cfg(feature = "adc3")] -bus_reset!(ADC3 => 8); - -#[cfg(any( - feature = "gpio-f413", - feature = "gpio-f469", - feature = "stm32f429", - feature = "stm32f439" -))] -bus! { - SAI => (APB2, 22), -} - -#[cfg(any(feature = "stm32f427", feature = "stm32f437", feature = "stm32f446"))] -bus! { - SAI1 => (APB2, 22), -} - -#[cfg(feature = "sai2")] -bus! { - SAI2 => (APB2, 23), -} - -#[cfg(feature = "sdio")] -bus! { - SDIO => (APB2, 11), -} - -bus! { - TIM1 => (APB2, 0), - TIM5 => (APB1, 3), - TIM9 => (APB2, 16), - TIM11 => (APB2, 18), -} - -#[cfg(any( - feature = "gpio-f401", - feature = "gpio-f417", - feature = "gpio-f411", - feature = "gpio-f412", - feature = "gpio-f413", - feature = "gpio-f427", - feature = "gpio-f446", - feature = "gpio-f469", -))] -bus! { - TIM2 => (APB1, 0), - TIM3 => (APB1, 1), - TIM4 => (APB1, 2), - TIM10 => (APB2, 17), -} - -#[cfg(any( - feature = "gpio-f410", - feature = "gpio-f412", - feature = "gpio-f413", - feature = "gpio-f417", - feature = "gpio-f427", - feature = "gpio-f446", - feature = "gpio-f469", -))] -bus! { - TIM6 => (APB1, 4), -} - -#[cfg(any( - feature = "gpio-f412", - feature = "gpio-f413", - feature = "gpio-f417", - feature = "gpio-f427", - feature = "gpio-f446", - feature = "gpio-f469", -))] -bus! { - TIM7 => (APB1, 5), - TIM8 => (APB2, 1), - TIM12 => (APB1, 6), - TIM13 => (APB1, 7), - TIM14 => (APB1, 8), -} - -#[cfg(feature = "ltdc")] -bus! { - LTDC => (APB2, 26), -} -#[cfg(feature = "dma2d")] -bus! { - DMA2D => (AHB1, 23), -} -#[cfg(feature = "dsihost")] -bus! { - DSI => (APB2, 27), -} diff --git a/src/rcc/f4/mod.rs b/src/rcc/f4/mod.rs index bde4bfb0..9f5ef134 100644 --- a/src/rcc/f4/mod.rs +++ b/src/rcc/f4/mod.rs @@ -1,212 +1,17 @@ use crate::pac::rcc::cfgr::{HPRE, SW}; -use crate::pac::{self, rcc, RCC}; +use crate::pac::RCC; -use super::{BusClock, BusTimerClock, RccBus}; +use super::*; use fugit::HertzU32 as Hertz; use fugit::RateExtU32; mod pll; -mod enable; -use crate::pac::rcc::RegisterBlock as RccRB; - -/// Enable/disable peripheral -#[allow(clippy::missing_safety_doc)] -pub trait Enable: RccBus { - /// Enables peripheral - fn enable(rcc: &RccRB); - - /// Disables peripheral - fn disable(rcc: &RccRB); - - /// Check if peripheral enabled - fn is_enabled() -> bool; - - /// Check if peripheral disabled - #[inline] - fn is_disabled() -> bool { - !Self::is_enabled() - } - - /// # Safety - /// - /// Enables peripheral. Takes access to RCC internally - unsafe fn enable_unchecked() { - let rcc = &*pac::RCC::ptr(); - Self::enable(rcc); - } - - /// # Safety - /// - /// Disables peripheral. Takes access to RCC internally - unsafe fn disable_unchecked() { - let rcc = pac::RCC::ptr(); - Self::disable(&*rcc); - } -} - -/// Low power enable/disable peripheral -#[allow(clippy::missing_safety_doc)] -pub trait LPEnable: RccBus { - /// Enables peripheral in low power mode - fn enable_in_low_power(rcc: &RccRB); - - /// Disables peripheral in low power mode - fn disable_in_low_power(rcc: &RccRB); - - /// Check if peripheral enabled in low power mode - fn is_enabled_in_low_power() -> bool; - - /// Check if peripheral disabled in low power mode - #[inline] - fn is_disabled_in_low_power() -> bool { - !Self::is_enabled_in_low_power() - } - - /// # Safety - /// - /// Enables peripheral in low power mode. Takes access to RCC internally - unsafe fn enable_in_low_power_unchecked() { - let rcc = pac::RCC::ptr(); - Self::enable_in_low_power(&*rcc); - } - - /// # Safety - /// - /// Disables peripheral in low power mode. Takes access to RCC internally - unsafe fn disable_in_low_power_unchecked() { - let rcc = pac::RCC::ptr(); - Self::disable_in_low_power(&*rcc); - } -} - -/// Reset peripheral -#[allow(clippy::missing_safety_doc)] -pub trait Reset: RccBus { - /// Resets peripheral - fn reset(rcc: &RccRB); - - /// # Safety - /// - /// Resets peripheral. Takes access to RCC internally - unsafe fn reset_unchecked() { - let rcc = pac::RCC::ptr(); - Self::reset(&*rcc); - } -} - -/// 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; -} - -macro_rules! bus_struct { - ($( $(#[$attr:meta])* $busX:ident => ($EN:ident, $en:ident, $LPEN:ident, $lpen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => { - $( - $(#[$attr])* - #[doc = $doc] - #[non_exhaustive] - pub struct $busX; - - $(#[$attr])* - impl $busX { - pub(crate) fn enr(rcc: &RccRB) -> &rcc::$EN { - rcc.$en() - } - - pub(crate) fn lpenr(rcc: &RccRB) -> &rcc::$LPEN { - rcc.$lpen() - } - - pub(crate) fn rstr(rcc: &RccRB) -> &rcc::$RST { - rcc.$rst() - } - } - )+ - }; -} - -bus_struct! { - APB1 => (APB1ENR, apb1enr, APB1LPENR, apb1lpenr, APB1RSTR, apb1rstr, "Advanced Peripheral Bus 1 (APB1) registers"), - APB2 => (APB2ENR, apb2enr, APB2LPENR, apb2lpenr, APB2RSTR, apb2rstr, "Advanced Peripheral Bus 2 (APB2) registers"), - AHB1 => (AHB1ENR, ahb1enr, AHB1LPENR, ahb1lpenr, AHB1RSTR, ahb1rstr, "Advanced High-performance Bus 1 (AHB1) registers"), - #[cfg(not(feature = "gpio-f410"))] - AHB2 => (AHB2ENR, ahb2enr, AHB2LPENR, ahb2lpenr, AHB2RSTR, ahb2rstr, "Advanced High-performance Bus 2 (AHB2) registers"), - //#[cfg(any(feature = "fsmc", feature = "fmc"))] - //AHB3 => (AHB3ENR, ahb3enr, AHB3LPENR, ahb3lpenr, AHB3RSTR, ahb3rstr, "Advanced High-performance Bus 3 (AHB3) registers"), -} - -/// AMBA High-performance Bus 3 (AHB3) registers -#[cfg(any(feature = "fsmc", feature = "fmc"))] -#[non_exhaustive] -pub struct AHB3; - -#[cfg(any(feature = "fsmc", feature = "fmc"))] -impl AHB3 { - #[inline(always)] - fn enr(rcc: &RccRB) -> &rcc::AHB3ENR { - rcc.ahb3enr() - } - #[cfg(feature = "fmc")] - #[inline(always)] - fn lpenr(rcc: &RccRB) -> &rcc::AHB3LPENR { - rcc.ahb3lpenr() - } - #[inline(always)] - fn rstr(rcc: &RccRB) -> &rcc::AHB3RSTR { - rcc.ahb3rstr() - } -} - -impl BusClock for AHB1 { - fn clock(clocks: &Clocks) -> Hertz { - clocks.hclk - } -} - -#[cfg(not(feature = "gpio-f410"))] -impl BusClock for AHB2 { - fn clock(clocks: &Clocks) -> Hertz { - clocks.hclk - } -} - -#[cfg(any(feature = "fsmc", feature = "fmc"))] -impl BusClock for AHB3 { - fn clock(clocks: &Clocks) -> Hertz { - clocks.hclk - } -} - -impl BusClock for APB1 { - fn clock(clocks: &Clocks) -> Hertz { - clocks.pclk1 - } -} - -impl BusClock for APB2 { - fn clock(clocks: &Clocks) -> Hertz { - clocks.pclk2 - } -} - -impl BusTimerClock for APB1 { - fn timer_clock(clocks: &Clocks) -> Hertz { - clocks.timclk1 - } -} - -impl BusTimerClock for APB2 { - fn timer_clock(clocks: &Clocks) -> Hertz { - clocks.timclk2 - } -} - impl RccExt for RCC { fn constrain(self) -> Rcc { Rcc { + rb: self, cfgr: CFGR { hse: None, hse_bypass: false, @@ -233,11 +38,6 @@ impl RccExt for RCC { } } -/// Constrained RCC peripheral -pub struct Rcc { - pub cfgr: CFGR, -} - /// Built-in high speed clock frequency pub const HSI: u32 = 16_000_000; // Hz @@ -917,31 +717,31 @@ impl RealSaiClocks { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Clocks { - hclk: Hertz, - pclk1: Hertz, - pclk2: Hertz, - timclk1: Hertz, - timclk2: Hertz, - sysclk: Hertz, - pll48clk: Option, + pub(super) hclk: Hertz, + pub(super) pclk1: Hertz, + pub(super) pclk2: Hertz, + pub(super) timclk1: Hertz, + pub(super) timclk2: Hertz, + pub(super) sysclk: Hertz, + pub(super) pll48clk: Option, #[cfg(not(feature = "rcc_i2s_apb"))] - i2s_clk: Option, + pub(super) i2s_clk: Option, #[cfg(feature = "rcc_i2s_apb")] - i2s_apb1_clk: Option, + pub(super) i2s_apb1_clk: Option, #[cfg(feature = "rcc_i2s_apb")] - i2s_apb2_clk: Option, + pub(super) i2s_apb2_clk: Option, #[cfg(feature = "sai")] #[cfg(not(feature = "sai2"))] - saia_clk: Option, + pub(super) saia_clk: Option, #[cfg(feature = "sai")] #[cfg(not(feature = "sai2"))] - saib_clk: Option, + pub(super) saib_clk: Option, #[cfg(feature = "sai2")] - sai1_clk: Option, + pub(super) sai1_clk: Option, #[cfg(feature = "sai2")] - sai2_clk: Option, + pub(super) sai2_clk: Option, } impl Clocks { diff --git a/src/rcc/f7/mod.rs b/src/rcc/f7/mod.rs new file mode 100644 index 00000000..f9beeccb --- /dev/null +++ b/src/rcc/f7/mod.rs @@ -0,0 +1,1204 @@ +//! Reset and clock control. + +use core::cmp::min; + +use super::*; + +#[cfg_attr(test, allow(unused_imports))] +use micromath::F32Ext; + +use crate::pac::{FLASH, PWR, RCC}; +use fugit::{HertzU32 as Hertz, RateExtU32}; + +/// Typical output frequency of the HSI oscillator. +const HSI_FREQUENCY: Hertz = Hertz::from_raw(16_000_000); + +impl RccExt for RCC { + fn constrain(self) -> Rcc { + Rcc { + rb: self, + cfgr: CFGR { + hse: None, + hse_bypass: false, + hclk: None, + sysclk: None, + pclk1: None, + pclk2: None, + lse: None, + lsi: None, + use_pll: false, + pll48clk: None, + pllm: 2, + plln: 50, + pllp: PLLP::Div2, + pllq: 2, + use_pllsai: false, + pllsain: 192, + pllsaip: PLLSAIP::Div2, + pllsaiq: 2, + use_plli2s: false, + plli2sr: 2, + plli2sq: 2, + plli2sn: 192, + mco1: MCO1::Hsi, + mco1pre: MCOPRE::Div1_no_div, + mco2: MCO2::Sysclk, + mco2pre: MCOPRE::Div1_no_div, + }, + } + } +} + +/*impl HSEClock { + /// Provide HSE frequency. + /// + /// # Panics + /// + /// Panics if the frequency is outside the valid range. The frequency must be between + /// 4 MHz and 26 MHz in oscillator mode and between 1 MHz and 50 MHz in bypass mode. + pub fn new(freq: Hertz, mode: HSEClockMode) -> Self { + let valid_range = match mode { + // Source: Datasheet DS12536 Rev 2, Table 38 + HSEClockMode::Oscillator => Hertz::MHz(4)..=Hertz::MHz(26), + // Source: Datasheet DS12536 Rev 2, Table 40 + HSEClockMode::Bypass => Hertz::MHz(1)..=Hertz::MHz(50), + }; + assert!(valid_range.contains(&freq)); + + HSEClock { freq, mode } + } +}*/ + +/// LSE clock mode. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum LSEClockMode { + /// Enable LSE oscillator to use external crystal or ceramic resonator. + Oscillator, + /// Bypass LSE oscillator to use external clock source. + /// Use this if an external oscillator is used which is not connected to `OSC32_IN` such as a MEMS resonator. + Bypass, +} + +/// LSE Clock. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct LSEClock { + /// Input frequency. + freq: Hertz, + /// Mode. + mode: LSEClockMode, +} + +impl LSEClock { + /// Provide LSE frequency. + pub fn new(mode: LSEClockMode) -> Self { + // Sets the LSE clock source to 32.768 kHz. + LSEClock { + freq: 32_768.Hz(), + mode, + } + } +} + +/// PLL P division factors. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PLLP { + Div2 = 0b00, + Div4 = 0b01, + Div6 = 0b10, + Div8 = 0b11, +} + +/// MCO prescaler +/// +/// Value on reset: No division +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum MCOPRE { + /// No division + Div1_no_div, + /// Division by 2 + Div2, + /// Division by 3 + Div3, + /// Division by 4 + Div4, + /// Division by 5 + Div5, +} + +/// PLL48CLK clock source selection +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PLL48CLK { + /// 48 MHz clock from PLLQ is selected + Pllq, + /// 48 MHz clock from PLLSAI is selected + Pllsai, +} + +/// PLLSAIP division factors. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PLLSAIP { + Div2 = 0b00, + Div4 = 0b01, + Div6 = 0b10, + Div8 = 0b11, +} + +/// Microcontroller clock output 1 +/// +/// Value on reset: HSI +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum MCO1 { + /// HSI clock selected + Hsi, + /// LSE oscillator selected + Lse, + /// HSE oscillator clock selected + Hse, + /// PLL clock selected + Pll, +} + +/// Microcontroller clock output 2 +/// +/// Value on reset: SYSCLK +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum MCO2 { + /// System clock (SYSCLK) selected + Sysclk, + /// PLLI2S clock selected + Plli2s, + /// HSE oscillator clock selected + Hse, + /// PLL clock selected + Pll, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +enum VOSscale { + PwrScale1, + PwrScale2, + #[default] + PwrScale3, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +struct InternalRCCConfig { + hpre: u8, + ppre1: u8, + ppre2: u8, + flash_waitstates: u8, + overdrive: bool, + vos_scale: VOSscale, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +struct FreqRequest { + p: Option<(u32, u32)>, + q: Option<(u32, u32)>, +} + +/// Clock configuration register. +#[derive(Debug, PartialEq, Eq)] +pub struct CFGR { + hse: Option, + hse_bypass: bool, + hclk: Option, + sysclk: Option, + pclk1: Option, + pclk2: Option, + lse: Option, + lsi: Option, + use_pll: bool, + pll48clk: Option, + pllm: u8, + plln: u16, + pllp: PLLP, + pllq: u8, + use_pllsai: bool, + pllsain: u16, + pllsaip: PLLSAIP, + pllsaiq: u8, + use_plli2s: bool, + plli2sr: u8, + plli2sq: u8, + plli2sn: u16, + mco1: MCO1, + mco1pre: MCOPRE, + mco2: MCO2, + mco2pre: MCOPRE, +} + +impl CFGR { + /// Configures the HSE oscillator. + pub fn use_hse(mut self, hse: Hertz) -> Self { + self.hse = Some(hse.raw()); + self + } + + /// Sets HCLK frequency. + /// + /// The HCLK is used for the AHB bus, core, memory and DMA. + /// + /// # Panics + /// + /// Panics if the frequency is larger than 216 MHz. + pub fn hclk(mut self, freq: Hertz) -> Self { + assert!(freq.raw() <= 216_000_000); + + self.hclk = Some(freq.raw()); + self + } + + /// Sets the SYSCLK frequency. + /// + /// This sets the SYSCLK frequency and sets up the USB clock if defined. + /// The provided frequency must be between 12.5 Mhz and 216 Mhz. + /// 12.5 Mhz is the VCO minimum frequency and SYSCLK PLLP divider limitation. + /// If the ethernet peripheral is on, the user should set a frequency higher than 25 Mhz. + /// + /// # Panics + /// + /// Panics if the frequency is not between 12.5 MHz and 216 MHz. + pub fn sysclk(mut self, sysclk: Hertz) -> Self { + assert!((12_500_000..=216_000_000).contains(&sysclk.raw())); + + self.sysclk = Some(sysclk.raw()); + self + } + + /// Sets the PCLK1 clock (APB1 clock). + /// + /// If this method isn't called the maximum allowed frequency is used for PCLK1. + /// + /// # Panics + /// + /// Panics if the frequency is not between 12.5 MHz and 54 MHz. + pub fn pclk1(mut self, freq: Hertz) -> Self { + assert!((12_500_000..=54_000_000).contains(&freq.raw())); + + self.pclk1 = Some(freq.raw()); + self + } + + /// Sets PCLK2 clock (APB2 clock). + /// + /// If this method isn't called the maximum allowed frequency is used for PCLK2. + /// + /// # Panics + /// + /// Panics if the frequency is not between 12.5 MHz and 108 MHz. + pub fn pclk2(mut self, freq: Hertz) -> Self { + assert!((12_500_000..=108_000_000).contains(&freq.raw())); + + self.pclk2 = Some(freq.raw()); + self + } + + /// Sets the LSE clock source to 32.768 kHz. + pub fn lse(mut self, lse: LSEClock) -> Self { + self.lse = Some(lse); + self + } + + /// Sets the LSI clock source to 32 kHz. + /// + /// Be aware that the tolerance is up to ±47% (Min 17 kHz, Typ 32 kHz, Max 47 kHz). + pub fn lsi(mut self) -> Self { + self.lsi = Some(32.kHz()); + self + } + + /// Sets the SYSCLK clock source to the main PLL. + /// + /// Note: `sysclk` must be specified or `use_pll48clk` must be set to true, otherwise `use_pll` is reset to false. + pub fn use_pll(mut self) -> Self { + self.use_pll = true; + self + } + + /// Sets the 48 MHz clock source. + pub fn use_pll48clk(mut self, pll48clk: PLL48CLK) -> Self { + self.pll48clk = Some(pll48clk); + self + } + + /// Sets the common PLL division factor. + /// + /// # Panics + /// + /// Panics if the division factor isn't between 2 and 63. + pub fn pllm(mut self, pllm: u8) -> Self { + assert!((2..=63).contains(&pllm)); + self.pllm = pllm; + self + } + + /// Sets the PLL multiplication factor for the main PLL. + /// + /// # Panics + /// + /// Panics if the multiplication factor isn't between 50 and 432 (inclusive). + pub fn plln(mut self, plln: u16) -> Self { + assert!((50..=432).contains(&plln)); + self.plln = plln; + self + } + + /// Sets the PLL division factor for the main PLL. + pub fn pllp(mut self, pllp: PLLP) -> Self { + self.pllp = pllp; + self + } + + /// Sets the PLL division factor for the 48 MHz clock. + /// # Panics + /// + /// Panics if the division factor isn't between 2 and 15 (inclusive). + pub fn pllq(mut self, pllq: u8) -> Self { + assert!((2..=15).contains(&pllq)); + self.pllq = pllq; + self + } + + /// Enables the PLLSAI clock source. + pub fn use_pllsai(mut self) -> Self { + self.use_pllsai = true; + self + } + + /// Sets the PLLSAIN multiplication factor for PLLSAI. + /// + /// # Panics + /// + /// Panics if the multiplication factor isn't between 50 and 432. + pub fn pllsain(mut self, pllsain: u16) -> Self { + assert!((50..=432).contains(&pllsain)); + self.pllsain = pllsain; + self + } + + /// Sets the PLLSAIP division factor for PLLSAI. + pub fn pllsaip(mut self, pllsaip: PLLSAIP) -> Self { + self.pllsaip = pllsaip; + self + } + + /// Sets the PLLSAIQ division factor for PLLSAIS. + /// + /// # Panics + /// + /// Panics if the division factor isn't between 2 and 15. + pub fn pllsaiq(mut self, pllsaiq: u8) -> Self { + assert!((2..=15).contains(&pllsaiq)); + self.pllsaiq = pllsaiq; + self + } + + /// Enables the PLLI2S clock source. + pub fn use_plli2s(mut self) -> Self { + self.use_plli2s = true; + self + } + + /// Sets the PLLI2SN multiplication factor for PLLI2S. + /// + /// # Panics + /// + /// Panics if the multiplication factor isn't between 50 and 432. + pub fn plli2sn(mut self, plli2sn: u16) -> Self { + assert!((50..=432).contains(&plli2sn)); + self.plli2sn = plli2sn; + self + } + + /// Sets the PLLI2SQ division factor for PLLI2S. + /// + /// # Panics + /// + /// Panics if the division factor isn't between 2 and 15. + pub fn plli2sq(mut self, plli2sq: u8) -> Self { + assert!((2..=15).contains(&plli2sq)); + self.plli2sq = plli2sq; + self + } + + /// Sets the PLLI2SR division factor for PLLI2S. + /// + /// # Panics + /// + /// Panics if the division factor isn't between 2 and 7. + pub fn plli2sr(mut self, plli2sr: u8) -> Self { + assert!((2..=7).contains(&plli2sr)); + self.plli2sr = plli2sr; + self + } + + /// Sets the MCO1 source + pub fn mco1(mut self, mco1: MCO1) -> Self { + self.mco1 = mco1; + self + } + + /// Sets the MCO1 division factors + pub fn mco1pre(mut self, mco1pre: MCOPRE) -> Self { + self.mco1pre = mco1pre; + self + } + + /// Sets the MCO2 source + pub fn mco2(mut self, mco2: MCO2) -> Self { + self.mco2 = mco2; + self + } + + /// Sets the MCO2 division factors + pub fn mco2pre(mut self, mco2pre: MCOPRE) -> Self { + self.mco2pre = mco2pre; + self + } + // We want to avoid dividing u64 values, because the Cortex-M7 CPU doesn't + // have hardware instructions for that, and the software divide that LLVM + // gives us is a relatively large amount of code. + // + // To do this, we operate in a fixed-point domain, and do a multiply by 1/x + // instead of dividing by x. We can calculate those 1/x values in a u32, if + // the fixed-point decimal place is chosen to be close enough to the LSB. + // + // But we also need to be able to represent the largest numerator, so we + // need enough bits to the left of the virtual decimal point. + // + // All of the chunks of code that do this are structured like: + // + // base_clk * n / m / p + // + // and they all have the same base_clk and n ranges (n up to 432, base_clk + // up to 50MHz). So base*plln can be as high as 216_000_000_000, and to + // represent that we need 38 bits. + // + // (We could use just 37 bits in one of these cases, if we take into account + // that high values of base_clk preclude using high values of n. But the + // other case is checking the output, so we can't assume anything about the + // inputs there.) + // + // So use 26 bits on the right of the decimal place. + // + // Also note, we need to round the 1/x values, not truncate them. So we + // shift left by one more bit, add one, and shift right by one. + const FIXED_POINT_LSHIFT: u32 = 31; + const FIXED_POINT_RSHIFT: u32 = 30; + + // We also drop 4 bits from the base_clk so that it and the fractional part + // (above) can fit into 64 bits. The max base_clk*n value needs 38 bits; + // shifting this out means it can fit into 34, with 30 (above) for the + // fractions. + const BASE_CLK_SHIFT: u32 = 4; + + /// Output clock calculation + fn calculate_clocks(&self) -> (Clocks, InternalRCCConfig) { + let mut config = InternalRCCConfig::default(); + + let base_clk = u64::from(self.hse.unwrap_or(HSI_FREQUENCY.raw())) >> Self::BASE_CLK_SHIFT; + + let mut sysclk = base_clk << Self::BASE_CLK_SHIFT; + + let mut pll48clk_valid = false; + + if self.use_pll { + // These initial divisions have to operate on u32 values to avoid + // the software division. Fortunately our 26 bit choice for the + // decimal place, and the fact that these are 1/N, means we can + // fit them into 26 bits, so a u32 is fine. + let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1; + let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT) + / match self.pllp { + PLLP::Div2 => 2u32, + PLLP::Div4 => 4u32, + PLLP::Div6 => 6u32, + PLLP::Div8 => 8u32, + } + + 1) + >> 1; + sysclk = (((base_clk * self.plln as u64 * one_over_m as u64) + >> Self::FIXED_POINT_RSHIFT) + * one_over_p as u64) + >> Self::FIXED_POINT_RSHIFT + << Self::BASE_CLK_SHIFT; + } + + // Check if pll48clk is valid + if let Some(pll48clk) = self.pll48clk { + match pll48clk { + PLL48CLK::Pllq => { + pll48clk_valid = { + let one_over_m = + ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1; + let one_over_q = + ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllq as u32) + 1) >> 1; + let pll48clk = (((base_clk * self.plln as u64 * one_over_m as u64) + >> Self::FIXED_POINT_RSHIFT) + * one_over_q as u64) + >> Self::FIXED_POINT_RSHIFT + << Self::BASE_CLK_SHIFT; + (48_000_000 - 120_000..=48_000_000 + 120_000).contains(&pll48clk) + } + } + PLL48CLK::Pllsai => { + pll48clk_valid = { + if self.use_pllsai { + // base_clk * pllsain has the same range as above + let one_over_m = + ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1; + let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT) + / match self.pllsaip { + PLLSAIP::Div2 => 2u32, + PLLSAIP::Div4 => 4u32, + PLLSAIP::Div6 => 6u32, + PLLSAIP::Div8 => 8u32, + } + + 1) + >> 1; + let pll48clk = (((base_clk * self.pllsain as u64 * one_over_m as u64) + >> Self::FIXED_POINT_RSHIFT) + * one_over_p as u64) + >> Self::FIXED_POINT_RSHIFT + << Self::BASE_CLK_SHIFT; + (48_000_000 - 120_000..=48_000_000 + 120_000).contains(&pll48clk) + } else { + false + } + } + } + } + } + + // SYSCLK, must be <= 216 Mhz. By default, HSI/HSE frequency is chosen + assert!(sysclk <= 216_000_000); + let sysclk = sysclk as u32; + + // HCLK. By default, SYSCLK frequency is chosen. Because of the method + // of clock multiplication and division, even if `sysclk` is set to be + // the same as `hclk`, it can be slightly inferior to `sysclk` after + // pllm, pllp... calculations + let mut hclk: u32 = min(sysclk, self.hclk.unwrap_or(sysclk)); + + // Configure HPRE. + let hpre_val: f32 = (sysclk as f32 / hclk as f32).ceil(); + + // The real value of hpre is computed to be as near as possible to the + // desired value, this leads to a quantization error + let (hpre_val, hpre): (f32, u8) = match hpre_val as u32 { + 0 => unreachable!(), + 1 => (1.0, 0b000), + 2 => (2.0, 0b1000), + 3..=5 => (4.0, 0b1001), + 6..=11 => (8.0, 0b1010), + 12..=39 => (16.0, 0b1011), + 40..=95 => (64.0, 0b1100), + 96..=191 => (128.0, 0b1101), + 192..=383 => (256.0, 0b1110), + _ => (512.0, 0b1111), + }; + config.hpre = hpre; + // update hclk with the real value + hclk = (sysclk as f32 / hpre_val).floor() as u32; + + // PCLK1 (APB1). Must be <= 54 Mhz. By default, min(hclk, 54Mhz) is + // chosen + // Add limits dependens on OD follows by DS Table 16. + let max_pclk1 = if sysclk <= 180_000_000 { + 45_000_000 + } else { + 54_000_000 + }; + let mut pclk1: u32 = min(max_pclk1, self.pclk1.unwrap_or(hclk)); + // PCLK2 (APB2). Must be <= 108 Mhz. By default, min(hclk, 108Mhz) is + // chosen + // Add limits dependens on OD follows by DS Table 16. + let max_pclk2 = if sysclk <= 180_000_000 { + 90_000_000 + } else { + 108_000_000 + }; + let mut pclk2: u32 = min(max_pclk2, self.pclk2.unwrap_or(hclk)); + + // Configure PPRE1 + let mut ppre1_val: u32 = (hclk as f32 / pclk1 as f32).ceil() as u32; + config.ppre1 = match ppre1_val { + 0 => unreachable!(), + 1 => { + ppre1_val = 1; + 0b000 + } + 2 => { + ppre1_val = 2; + 0b100 + } + 3..=6 => { + ppre1_val = 4; + 0b101 + } + 7..=12 => { + ppre1_val = 8; + 0b110 + } + _ => { + ppre1_val = 16; + 0b111 + } + }; + // update pclk1 with the real value + pclk1 = hclk / ppre1_val; + + // Configure PPRE2 + let mut ppre2_val: u32 = (hclk as f32 / pclk2 as f32).ceil() as u32; + config.ppre2 = match ppre2_val { + 0 => unreachable!(), + 1 => { + ppre2_val = 1; + 0b000 + } + 2 => { + ppre2_val = 2; + 0b100 + } + 3..=6 => { + ppre2_val = 4; + 0b101 + } + 7..=12 => { + ppre2_val = 8; + 0b110 + } + _ => { + ppre2_val = 16; + 0b111 + } + }; + // update pclk2 with the real value + pclk2 = hclk / ppre2_val; + + // Assumes TIMPRE bit of RCC_DCKCFGR1 is reset (0) + let timclk1 = if ppre1_val == 1 { pclk1 } else { 2 * pclk1 }; + let timclk2 = if ppre2_val == 1 { pclk2 } else { 2 * pclk2 }; + + // Adjust flash wait states + config.flash_waitstates = if sysclk <= 30_000_000 { + 0b0000 + } else if sysclk <= 60_000_000 { + 0b0001 + } else if sysclk <= 90_000_000 { + 0b0010 + } else if sysclk <= 120_000_000 { + 0b0011 + } else if sysclk <= 150_000_000 { + 0b0100 + } else if sysclk <= 180_000_000 { + 0b0101 + } else if sysclk <= 210_000_000 { + 0b0110 + } else { + 0b0111 + }; + // Adjust power state and overdrive mode + // Configure follows by RM 4.1.4 + // Values getted from DS Table 16. General operating conditions + config.vos_scale = if sysclk <= 144_000_000 { + VOSscale::PwrScale3 + } else if sysclk <= 168_000_000 { + VOSscale::PwrScale2 + } else { + VOSscale::PwrScale1 + }; + // For every frequency higher than 180 need to enable overdrive + // Follows by DS Table 16. + config.overdrive = sysclk > 180_000_000; + + let clocks = Clocks { + hclk: hclk.Hz(), + pclk1: pclk1.Hz(), + pclk2: pclk2.Hz(), + sysclk: sysclk.Hz(), + timclk1: timclk1.Hz(), + timclk2: timclk2.Hz(), + pll48clk_valid, + hse: self.hse.map(|hse| hse.Hz()), + lse: self.lse.map(|lse| lse.freq), + lsi: self.lsi, + }; + + (clocks, config) + } + + /// Calculate the PLL M, N, P and Q values from the provided clock and requested options. + fn calculate_mnpq( + f_pll_clock_input: u32, + freq_req: FreqRequest, + ) -> Option<(u32, u32, Option, Option)> { + let mut m = 2; + let mut n = 432; + let mut p = None; + let mut q = None; + + if freq_req.p.is_none() && freq_req.q.is_none() { + return None; + } + + loop { + if m > 63 { + return None; + } + let f_vco_input = f_pll_clock_input / m; + if f_vco_input < 1_000_000 { + return None; + } + if f_vco_input > 2_000_000 || n < 50 { + m += 1; + n = 432; + continue; + } + // See the comments around Self::FIXED_POINT_LSHIFT to see how this works. + let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / m + 1) >> 1; + let f_vco_clock = (((f_pll_clock_input as u64 >> Self::BASE_CLK_SHIFT) + * n as u64 + * one_over_m as u64) + >> Self::FIXED_POINT_RSHIFT + << Self::BASE_CLK_SHIFT) as u32; + if f_vco_clock < 50_000_000 { + m += 1; + n = 432; + continue; + } + if f_vco_clock > 432_000_000 { + n -= 1; + continue; + } + + if let Some((p_freq_min, p_freq_max)) = freq_req.p { + let mut div = None; + for div_p in &[2, 4, 6, 8] { + let f_pll_clock_output = f_vco_clock / div_p; + if f_pll_clock_output >= p_freq_min && f_pll_clock_output <= p_freq_max { + div = Some(*div_p) + } + } + if div.is_some() { + p = div; + if freq_req.q.is_none() { + break; + } + } else { + n -= 1; + continue; + } + } + + if let Some((q_freq_min, q_freq_max)) = freq_req.q { + let mut div = None; + for div_q in 2..=15 { + let f_usb_clock_output = f_vco_clock / div_q; + if f_usb_clock_output >= q_freq_min && f_usb_clock_output <= q_freq_max { + div = Some(div_q) + } + } + if div.is_some() { + q = div; + break; + } else { + n -= 1; + continue; + } + } + } + + Some((m, n, p, q)) + } + + fn pll_configure(&mut self) { + let base_clk = self.hse.unwrap_or(HSI_FREQUENCY.raw()) >> Self::BASE_CLK_SHIFT; + + let sysclk = if let Some(clk) = self.sysclk { + clk + } else { + base_clk << Self::BASE_CLK_SHIFT + }; + + let p = if base_clk << Self::BASE_CLK_SHIFT == sysclk { + None + } else { + Some((sysclk - 1, sysclk + 1)) + }; + + let q = if let Some(PLL48CLK::Pllq) = self.pll48clk { + Some((48_000_000 - 120_000, 48_000_000 + 120_000)) + } else { + None + }; + + if p.is_none() && q.is_none() { + // We don't need PLL + self.use_pll = false; + return; + } + + // We check if (pllm, plln, pllp) allow to obtain the requested Sysclk, + // so that we don't have to calculate them + let one_over_m = ((1 << Self::FIXED_POINT_LSHIFT) / (self.pllm as u32) + 1) >> 1; + let one_over_p = ((1 << Self::FIXED_POINT_LSHIFT) + / match self.pllp { + PLLP::Div2 => 2u32, + PLLP::Div4 => 4u32, + PLLP::Div6 => 6u32, + PLLP::Div8 => 8u32, + } + + 1) + >> 1; + let p_ok = (sysclk as u64) + == (((base_clk as u64 * self.plln as u64 * one_over_m as u64) + >> Self::FIXED_POINT_RSHIFT) + * one_over_p as u64) + >> Self::FIXED_POINT_RSHIFT + << Self::BASE_CLK_SHIFT; + if p_ok && q.is_none() { + return; + } + + if let Some((m, n, p, q)) = + CFGR::calculate_mnpq(base_clk << Self::BASE_CLK_SHIFT, FreqRequest { p, q }) + { + self.pllm = m as u8; + self.plln = n as u16; + if let Some(p) = p { + self.use_pll = true; + self.pllp = match p { + 2 => PLLP::Div2, + 4 => PLLP::Div4, + 6 => PLLP::Div6, + 8 => PLLP::Div8, + _ => unreachable!(), + }; + } + if let Some(q) = q { + self.pllq = q as u8; + } + } else { + panic!("couldn't calculate {} from {}", sysclk, base_clk); + } + } + + /// Configures the default clock settings. + /// + /// Set SYSCLK as 216 Mhz and setup USB clock if defined. + pub fn set_defaults(self) -> Self { + self.sysclk(216.MHz()) + } + + /// Configure the "mandatory" clocks (`sysclk`, `hclk`, `pclk1` and `pclk2') + /// and return them via the `Clocks` struct. + /// + /// The user shouldn't call freeze more than once as the clocks parameters + /// cannot be changed after the clocks have started. + /// + /// The implementation makes the following choice: HSI is always chosen over + /// HSE except when HSE is provided. When HSE is provided, HSE is used + /// wherever it is possible. + pub fn freeze(mut self) -> Clocks { + let flash = unsafe { &(*FLASH::ptr()) }; + let rcc = unsafe { &(*RCC::ptr()) }; + let pwr = unsafe { &(*PWR::ptr()) }; + + self.pll_configure(); + + let (clocks, config) = self.calculate_clocks(); + + // Switch to fail-safe clock settings. + // This is useful when booting from a bootloader that alters clock tree configuration. + // Turn on HSI + rcc.cr().modify(|_, w| w.hsion().set_bit()); + while rcc.cr().read().hsirdy().bit_is_clear() {} + // Switch to HSI + rcc.cfgr().modify(|_, w| w.sw().hsi()); + + // Configure HSE if provided + if self.hse.is_some() { + // enable HSE and wait for it to be ready + rcc.cr().modify(|_, w| { + if self.hse_bypass { + w.hsebyp().bypassed(); + } + w.hseon().set_bit() + }); + while rcc.cr().read().hserdy().bit_is_clear() {} + } + + // Enable sequence follows by RM 4.1.4 Entering Overdrive mode. + if self.use_pll || self.pll48clk.is_some() { + // Disable PLL + // Since the main-PLL configuration parameters cannot be changed once PLL is enabled, it is + // recommended to configure PLL before enabling it (selection of the HSI or HSE oscillator as + // PLL clock source, and configuration of division factors M, N, P, and Q). + rcc.cr().modify(|_, w| w.pllon().off()); + + rcc.pllcfgr().modify(|_, w| unsafe { + w.pllm().bits(self.pllm); + w.plln().bits(self.plln); + w.pllp().bits(self.pllp as u8); + w.pllq().bits(self.pllq); + w.pllsrc().bit(self.hse.is_some()) + }); + + // Enable PWR domain and setup VOSscale and Overdrive options + rcc.apb1enr().modify(|_, w| w.pwren().set_bit()); + + pwr.cr1().modify(|_, w| match config.vos_scale { + VOSscale::PwrScale3 => w.vos().scale3(), + VOSscale::PwrScale2 => w.vos().scale2(), + VOSscale::PwrScale1 => w.vos().scale1(), + }); + + // Enable PLL + rcc.cr().modify(|_, w| w.pllon().on()); + + // Wait for PLL to stabilise + while rcc.cr().read().pllrdy().is_not_ready() {} + + //Over-drive + if config.overdrive { + // Entering Over-drive mode + //enable the Over-drive mode + pwr.cr1().modify(|_, w| w.oden().set_bit()); + + //wait for the ODRDY flag to be set + while !pwr.csr1().read().odrdy().bit_is_set() {} + + //switch the voltage regulator from Normal mode to Over-drive mode + pwr.cr1().modify(|_, w| w.odswen().set_bit()); + + //Wait for the ODSWRDY flag in the PWR_CSR1 to be set. + while !pwr.csr1().read().odswrdy().bit_is_set() {} + } + } + + // Configure LSE if provided + if self.lse.is_some() { + // Configure the LSE mode + match self.lse.as_ref().unwrap().mode { + LSEClockMode::Bypass => rcc.bdcr().modify(|_, w| w.lsebyp().bypassed()), + LSEClockMode::Oscillator => rcc.bdcr().modify(|_, w| w.lsebyp().not_bypassed()), + }; + // Enable the LSE. + rcc.bdcr().modify(|_, w| w.lseon().on()); + while rcc.bdcr().read().lserdy().is_not_ready() {} + } + + if self.lsi.is_some() { + rcc.csr().modify(|_, w| w.lsion().on()); + while rcc.csr().read().lsirdy().is_not_ready() {} + } + + if self.use_pllsai { + let pllsain_freq = match self.hse { + Some(hse) => hse as u64 / self.pllm as u64 * self.pllsain as u64, + None => 16_000_000 / self.pllm as u64 * self.pllsain as u64, + }; + let pllsaip_freq = pllsain_freq + / match self.pllsaip { + PLLSAIP::Div2 => 2, + PLLSAIP::Div4 => 4, + PLLSAIP::Div6 => 6, + PLLSAIP::Div8 => 8, + }; + // let pllsaiq_freq = pllsain_freq / self.pllsaiq as u64; + + // The reference manual (RM0410 Rev 4, Page 212), says the following + // "Caution: The software has to set these bits correctly to ensure that the VCO output frequency is between 100 and 432 MHz.", + // but STM32CubeMX states 192 MHz as the minimum. SSo the stricter requirement was chosen. + assert!((192_000_000..=432_000_000).contains(&pllsain_freq)); + assert!(pllsaip_freq <= 48_000_000); + + rcc.pllsaicfgr().modify(|_, w| unsafe { + w.pllsain().bits(self.pllsain); + w.pllsaip().bits(self.pllsaip as u8); + w.pllsaiq().bits(self.pllsaiq) + }); + rcc.cr().modify(|_, w| w.pllsaion().on()); + } + + if let Some(pll48clk) = self.pll48clk { + match pll48clk { + PLL48CLK::Pllq => rcc.dckcfgr2().modify(|_, w| w.ck48msel().bit(false)), + PLL48CLK::Pllsai => rcc.dckcfgr2().modify(|_, w| w.ck48msel().bit(true)), + }; + } + + if self.use_plli2s { + let plli2sn_freq = match self.hse { + Some(hse) => hse as u64 / self.pllm as u64 * self.plli2sn as u64, + None => 16_000_000 / self.pllm as u64 * self.plli2sn as u64, + }; + let plli2sr_freq = plli2sn_freq / self.plli2sr as u64; + let plli2sq_freq = plli2sn_freq / self.plli2sq as u64; + + assert!((192_000_000..=432_000_000).contains(&plli2sn_freq)); + assert!(plli2sr_freq <= 216_000_000); + assert!(plli2sq_freq <= 216_000_000); + + rcc.plli2scfgr().modify(|_, w| unsafe { + w.plli2sn().bits(self.plli2sn); + w.plli2sr().bits(self.plli2sr); + w.plli2sq().bits(self.plli2sq) + }); + rcc.cr().modify(|_, w| w.plli2son().on()); + } + + rcc.cfgr().modify(|_, w| { + w.mco1() + .variant(self.mco1.into()) + .mco1pre() + .variant(self.mco1pre.into()); + w.mco2() + .variant(self.mco2.into()) + .mco2pre() + .variant(self.mco2pre.into()) + }); + + flash + .acr() + .write(|w| w.latency().set(config.flash_waitstates)); + + // Configure HCLK, PCLK1, PCLK2 + rcc.cfgr().modify(|_, w| unsafe { + w.ppre1() + .bits(config.ppre1) + .ppre2() + .bits(config.ppre2) + .hpre() + .bits(config.hpre) + }); + + // Select SYSCLK source + if self.use_pll { + rcc.cfgr().modify(|_, w| w.sw().pll()); + while !rcc.cfgr().read().sws().is_pll() {} + } else if self.hse.is_some() { + rcc.cfgr().modify(|_, w| w.sw().hse()); + while !rcc.cfgr().read().sws().is_hse() {} + } else { + rcc.cfgr().modify(|_, w| w.sw().hsi()); + while !rcc.cfgr().read().sws().is_hsi() {} + } + + // As requested by user manual we need to wait 16 ticks before the right + // predivision is applied + cortex_m::asm::delay(16); + + clocks + } +} + +/// Frozen clock frequencies +/// +/// The existence of this value indicates that the clock configuration can no longer be changed +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Clocks { + pub(super) hclk: Hertz, + pub(super) pclk1: Hertz, + pub(super) pclk2: Hertz, + pub(super) sysclk: Hertz, + pub(super) timclk1: Hertz, + pub(super) timclk2: Hertz, + pub(super) pll48clk_valid: bool, + pub(super) hse: Option, + pub(super) lse: Option, + pub(super) lsi: Option, +} + +impl Clocks { + /// Returns the frequency of the AHB1 + pub fn hclk(&self) -> Hertz { + self.hclk + } + + /// Returns the frequency of the APB1 + pub fn pclk1(&self) -> Hertz { + self.pclk1 + } + + /// Returns the frequency of the APB2 + pub fn pclk2(&self) -> Hertz { + self.pclk2 + } + + /// Returns the system (core) frequency + pub fn sysclk(&self) -> Hertz { + self.sysclk + } + + /// Returns the frequency for timers on APB1 + pub fn timclk1(&self) -> Hertz { + self.timclk1 + } + + /// Returns the frequency for timers on APB1 + pub fn timclk2(&self) -> Hertz { + self.timclk2 + } + + /// Returns true if the PLL48 clock is within USB + /// specifications. It is required to use the USB functionality. + pub fn is_pll48clk_valid(&self) -> bool { + // USB specification allow +-0.25% + self.pll48clk_valid + } + + /// Returns the frequency of the `HSE` if `Some`, else `None`. + pub fn hse(&self) -> Option { + self.hse + } + + /// Returns the frequency of the `LSE` if `Some`, else `None`. + pub fn lse(&self) -> Option { + self.lse + } + + /// Returns the frequency of the `LSI` if `Some`, else `None`. + pub fn lsi(&self) -> Option { + self.lsi + } +} + +impl From for crate::pac::rcc::cfgr::MCO1 { + fn from(input: MCO1) -> Self { + match input { + MCO1::Hsi => Self::Hsi, + MCO1::Lse => Self::Lse, + MCO1::Hse => Self::Hse, + MCO1::Pll => Self::Pll, + } + } +} + +impl From for crate::pac::rcc::cfgr::MCO2 { + fn from(input: MCO2) -> Self { + match input { + MCO2::Sysclk => Self::Sysclk, + MCO2::Plli2s => Self::Plli2s, + MCO2::Hse => Self::Hse, + MCO2::Pll => Self::Pll, + } + } +} + +impl From for crate::pac::rcc::cfgr::MCO1PRE { + fn from(input: MCOPRE) -> Self { + match input { + MCOPRE::Div1_no_div => Self::Div1, + MCOPRE::Div2 => Self::Div2, + MCOPRE::Div3 => Self::Div3, + MCOPRE::Div4 => Self::Div4, + MCOPRE::Div5 => Self::Div5, + } + } +} + +#[cfg(test)] +mod tests; diff --git a/src/rcc/f7/tests.rs b/src/rcc/f7/tests.rs new file mode 100644 index 00000000..11c85c8c --- /dev/null +++ b/src/rcc/f7/tests.rs @@ -0,0 +1,277 @@ +use fugit::{HertzU32 as Hertz, RateExtU32}; + +use super::{FreqRequest, CFGR}; + +fn build_request(sysclk: u32, use_pll48clk: bool) -> FreqRequest { + let p = Some((sysclk - 1, sysclk + 1)); + let q = if use_pll48clk { + Some((48_000_000 - 120_000, 48_000_000 + 120_000)) + } else { + None + }; + FreqRequest { p, q } +} + +fn check(hse: u32, sysclk: u32, use_pll48clk: bool) { + let request = build_request(sysclk, use_pll48clk); + let (m, n, p, q) = CFGR::calculate_mnpq(hse, request).expect("Can't calculate PLL parameters"); + + let pll_in = hse; + + if m < 2 || m > 63 { + panic!("Invalid PLL M value: {}", m); + } + + let vco_in = pll_in / m; + if vco_in < 1_000_000 || vco_in > 2_000_000 { + panic!("Invalid VCO input frequency: {}", vco_in); + } + + if n < 50 || n > 432 { + panic!("Invalid PLL N value: {}", n); + } + + let vco = ((pll_in as u64) * (n as u64) / (m as u64)) as u32; + if vco < 100_000_000 || vco > 432_000_000 { + panic!("Invalid VCO frequency: {}", vco); + } + + let p = p.expect("PLL P value should be defined!"); + if [2, 4, 6, 8].iter().find(|v| **v == p).is_none() { + panic!("Invalid PLL P value: {}", p); + } + + let p_freq = vco / p; + if p_freq > 216_000_000 { + panic!("Invalid PLL P frequency: {}", p_freq); + } + if p_freq < (sysclk - 1) || p_freq > (sysclk + 1) { + panic!( + "Invalid PLL P frequency: {} (requested sysclk {})", + p_freq, sysclk + ); + } + + if use_pll48clk && q.is_none() { + panic!("PLL Q value should be defined!"); + } + if let Some(q) = q { + if q < 2 || q > 15 { + panic!("Invalid PLL Q value: {}", q); + } + if use_pll48clk { + let q_freq = vco / q; + if q_freq < (48_000_000 - 120_000) || q_freq > (48_000_000 + 120_000) { + panic!("Invalid PLL Q frequency: {}", q_freq); + } + } + } +} + +#[test] +fn test_pll_calc1() { + check(25_000_000, 48_000_000, false); +} + +#[test] +fn test_pll_calc1_usb() { + check(25_000_000, 48_000_000, true); +} + +#[test] +fn test_pll_calc2() { + check(12_000_000, 48_000_000, false); +} + +#[test] +fn test_pll_calc2_usb() { + check(12_000_000, 48_000_000, true); +} + +#[test] +fn test_pll_calc3() { + check(12_000_000, 216_000_000, false); +} + +#[test] +fn test_pll_calc3_usb() { + check(12_000_000, 216_000_000, true); +} + +#[test] +fn test_rcc_calc1() { + use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP}; + + let cfgr = CFGR { + hse: None, + hse_bypass: false, + hclk: None, + sysclk: None, + pclk1: None, + pclk2: None, + lse: None, + lsi: None, + use_pll: false, + pll48clk: None, + pllm: 2, + plln: 50, + pllp: PLLP::Div2, + pllq: 2, + use_pllsai: false, + pllsain: 192, + pllsaip: PLLSAIP::Div2, + pllsaiq: 2, + use_plli2s: false, + plli2sr: 2, + plli2sq: 2, + plli2sn: 192, + mco1: MCO1::Hsi, + mco1pre: MCOPRE::Div1_no_div, + mco2: MCO2::Sysclk, + mco2pre: MCOPRE::Div1_no_div, + }; + + let mut cfgr = cfgr + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) + .use_pll() + .use_pll48clk(PLL48CLK::Pllq) + .sysclk(216.MHz()); + cfgr.pll_configure(); + + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); + + let (clocks, _config) = cfgr.calculate_clocks(); + assert_eq!(clocks.sysclk().raw(), 216_000_000); + assert!(clocks.is_pll48clk_valid()); +} + +#[test] +fn test_rcc_calc2() { + use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP}; + + let cfgr = CFGR { + hse: None, + hse_bypass: false, + hclk: None, + sysclk: None, + pclk1: None, + pclk2: None, + lse: None, + lsi: None, + use_pll: false, + pll48clk: None, + pllm: 2, + plln: 50, + pllp: PLLP::Div2, + pllq: 2, + use_pllsai: false, + pllsain: 192, + pllsaip: PLLSAIP::Div2, + pllsaiq: 2, + use_plli2s: false, + plli2sr: 2, + plli2sq: 2, + plli2sn: 192, + mco1: MCO1::Hsi, + mco1pre: MCOPRE::Div1_no_div, + mco2: MCO2::Sysclk, + mco2pre: MCOPRE::Div1_no_div, + }; + + let mut cfgr = cfgr + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) + .use_pll48clk(PLL48CLK::Pllq) + .sysclk(216.MHz()); + cfgr.pll_configure(); + + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); + + let (clocks, _config) = cfgr.calculate_clocks(); + assert_eq!(clocks.sysclk().raw(), 216_000_000); + assert!(clocks.is_pll48clk_valid()); +} + +#[test] +fn test_rcc_calc3() { + use super::{HSEClock, HSEClockMode, MCO1, MCO2, MCOPRE, PLL48CLK, PLLP, PLLSAIP}; + + let cfgr = CFGR { + hse: None, + hse_bypass: false, + hclk: None, + sysclk: None, + pclk1: None, + pclk2: None, + lse: None, + lsi: None, + use_pll: false, + pll48clk: None, + pllm: 2, + plln: 50, + pllp: PLLP::Div2, + pllq: 2, + use_pllsai: false, + pllsain: 192, + pllsaip: PLLSAIP::Div2, + pllsaiq: 2, + use_plli2s: false, + plli2sr: 2, + plli2sq: 2, + plli2sn: 192, + mco1: MCO1::Hsi, + mco1pre: MCOPRE::Div1_no_div, + mco2: MCO2::Sysclk, + mco2pre: MCOPRE::Div1_no_div, + }; + + let mut cfgr = cfgr + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) + .use_pll48clk(PLL48CLK::Pllq) + .set_defaults(); + cfgr.pll_configure(); + + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); + + let (clocks, _config) = cfgr.calculate_clocks(); + assert_eq!(clocks.sysclk().raw(), 216_000_000); + assert!(clocks.is_pll48clk_valid()); +} + +#[test] +fn test_rcc_default() { + use super::{MCO1, MCO2, MCOPRE, PLLP, PLLSAIP}; + + let mut cfgr = CFGR { + hse: None, + hse_bypass: false, + hclk: None, + sysclk: None, + pclk1: None, + pclk2: None, + lse: None, + lsi: None, + use_pll: false, + pll48clk: None, + pllm: 2, + plln: 50, + pllp: PLLP::Div2, + pllq: 2, + use_pllsai: false, + pllsain: 192, + pllsaip: PLLSAIP::Div2, + pllsaiq: 2, + use_plli2s: false, + plli2sr: 2, + plli2sq: 2, + plli2sn: 192, + mco1: MCO1::Hsi, + mco1pre: MCOPRE::Div1_no_div, + mco2: MCO2::Sysclk, + mco2pre: MCOPRE::Div1_no_div, + }; + + cfgr.pll_configure(); + assert!(!cfgr.use_pll); + let (clocks, _config) = cfgr.calculate_clocks(); + assert_eq!(clocks.sysclk().raw(), 16_000_000); +} diff --git a/src/rcc/mod.rs b/src/rcc/mod.rs index f843f521..4d036fa4 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -39,11 +39,49 @@ //! 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. + +mod enable; + +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f4")] pub use f4::*; +#[cfg(feature = "f7")] +mod f7; +#[cfg(feature = "f7")] +pub use f7::*; + +use crate::pac::rcc::{self, RegisterBlock as RccRB}; +use crate::pac::RCC; +use core::ops::{Deref, DerefMut}; use fugit::HertzU32 as Hertz; +/// Constrained RCC peripheral +pub struct Rcc { + pub cfgr: CFGR, + pub(crate) rb: RCC, +} + +impl Deref for Rcc { + type Target = RCC; + fn deref(&self) -> &Self::Target { + &self.rb + } +} + +impl DerefMut for Rcc { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.rb + } +} + +/// 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; +} + /// Bus associated to peripheral pub trait RccBus: crate::Sealed { /// Bus type; @@ -81,3 +119,168 @@ where T::Bus::timer_clock(clocks) } } + +/// Enable/disable peripheral +pub trait Enable: RccBus { + /// Enables peripheral + fn enable(rcc: &mut RCC); + + /// Disables peripheral + fn disable(rcc: &mut RCC); + + /// Check if peripheral enabled + fn is_enabled() -> bool; + + /// Check if peripheral disabled + #[inline] + fn is_disabled() -> bool { + !Self::is_enabled() + } + + /// # Safety + /// + /// Enables peripheral. Takes access to RCC internally + unsafe fn enable_unchecked() { + let mut rcc = RCC::steal(); + Self::enable(&mut rcc); + } + + /// # Safety + /// + /// Disables peripheral. Takes access to RCC internally + unsafe fn disable_unchecked() { + let mut rcc = RCC::steal(); + Self::disable(&mut rcc); + } +} + +/// Low power enable/disable peripheral +pub trait LPEnable: RccBus { + /// Enables peripheral in low power mode + fn enable_in_low_power(rcc: &mut RCC); + + /// Disables peripheral in low power mode + fn disable_in_low_power(rcc: &mut RCC); + + /// Check if peripheral enabled in low power mode + fn is_enabled_in_low_power() -> bool; + + /// Check if peripheral disabled in low power mode + #[inline] + fn is_disabled_in_low_power() -> bool { + !Self::is_enabled_in_low_power() + } + + /// # Safety + /// + /// Enables peripheral in low power mode. Takes access to RCC internally + unsafe fn enable_in_low_power_unchecked() { + let mut rcc = RCC::steal(); + Self::enable_in_low_power(&mut rcc); + } + + /// # Safety + /// + /// Disables peripheral in low power mode. Takes access to RCC internally + unsafe fn disable_in_low_power_unchecked() { + let mut rcc = RCC::steal(); + Self::disable_in_low_power(&mut rcc); + } +} + +/// Reset peripheral +pub trait Reset: RccBus { + /// Resets peripheral + fn reset(rcc: &mut RCC); + + /// # Safety + /// + /// Resets peripheral. Takes access to RCC internally + unsafe fn reset_unchecked() { + let mut rcc = RCC::steal(); + Self::reset(&mut rcc); + } +} + +macro_rules! bus_struct { + ($($busX:ident => ($EN:ident, $en:ident, $LPEN:ident, $lpen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => { + $( + #[doc = $doc] + #[non_exhaustive] + pub struct $busX; + + impl $busX { + pub(crate) fn enr(rcc: &RccRB) -> &rcc::$EN { + rcc.$en() + } + + pub(crate) fn lpenr(rcc: &RccRB) -> &rcc::$LPEN { + rcc.$lpen() + } + + pub(crate) fn rstr(rcc: &RccRB) -> &rcc::$RST { + rcc.$rst() + } + } + )+ + }; +} +use bus_struct; + +bus_struct! { + APB1 => (APB1ENR, apb1enr, APB1LPENR, apb1lpenr, APB1RSTR, apb1rstr, "Advanced Peripheral Bus 1 (APB1) registers"), + APB2 => (APB2ENR, apb2enr, APB2LPENR, apb2lpenr, APB2RSTR, apb2rstr, "Advanced Peripheral Bus 2 (APB2) registers"), + AHB1 => (AHB1ENR, ahb1enr, AHB1LPENR, ahb1lpenr, AHB1RSTR, ahb1rstr, "Advanced High-performance Bus 1 (AHB1) registers"), +} +#[cfg(not(feature = "gpio-f410"))] +bus_struct! { + AHB2 => (AHB2ENR, ahb2enr, AHB2LPENR, ahb2lpenr, AHB2RSTR, ahb2rstr, "Advanced High-performance Bus 2 (AHB2) registers"), +} +#[cfg(any(feature = "f7", feature = "fsmc", feature = "fmc"))] +bus_struct! { + AHB3 => (AHB3ENR, ahb3enr, AHB3LPENR, ahb3lpenr, AHB3RSTR, ahb3rstr, "Advanced High-performance Bus 3 (AHB3) registers"), +} + +impl BusClock for AHB1 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.hclk + } +} + +#[cfg(not(feature = "gpio-f410"))] +impl BusClock for AHB2 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.hclk + } +} + +#[cfg(any(feature = "f7", feature = "fsmc", feature = "fmc"))] +impl BusClock for AHB3 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.hclk + } +} + +impl BusClock for APB1 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.pclk1 + } +} + +impl BusClock for APB2 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.pclk2 + } +} + +impl BusTimerClock for APB1 { + fn timer_clock(clocks: &Clocks) -> Hertz { + clocks.timclk1 + } +} + +impl BusTimerClock for APB2 { + fn timer_clock(clocks: &Clocks) -> Hertz { + clocks.timclk2 + } +} diff --git a/src/rng.rs b/src/rng.rs index 3d5645f8..0a97a4dc 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -23,12 +23,11 @@ use core::cmp; use core::mem; -use crate::pac::RNG; +use crate::pac::{RCC, RNG}; use crate::rcc::{Clocks, Enable, Reset}; use core::num::NonZeroU32; use core::ops::Shl; use embedded_hal_02::blocking::rng; -use fugit::RateExtU32; use rand_core::RngCore; /// Random number generator specific errors @@ -80,21 +79,34 @@ pub trait RngExt { } impl RngExt for RNG { - fn constrain(self, clocks: &Clocks) -> Rng { + fn constrain(self, _clocks: &Clocks) -> Rng { cortex_m::interrupt::free(|_| { + let rcc = unsafe { &*RCC::ptr() }; + // need set enable pll for this operation + if rcc.cr().read().pllrdy().bit_is_clear() { + rcc.cr().modify(|_, w| w.pllon().set_bit()); + // wait till pll is ready + while rcc.cr().read().pllrdy().bit_is_clear() {} + } + // enable RNG_CLK (peripheral clock) unsafe { + // enable RNG_CLK (peripheral clock) RNG::enable_unchecked(); + // give RNG_CLK time to start + RNG::is_enabled(); RNG::reset_unchecked(); } - // verify the clock configuration is valid - let hclk = clocks.hclk(); - let rng_clk = clocks.pll48clk().unwrap_or_else(|| 0.Hz()); - assert!(rng_clk >= (hclk / 16)); - // enable the RNG peripheral self.cr().modify(|_, w| w.rngen().set_bit()); + // hardware check for clock is used + // instead of software calculation, which may be inaccurate. + // until data is available we will check for CECS flag, if it is set + // means that clock error occured + while !self.sr().read().drdy().bit() { + assert!(!self.sr().read().cecs().bit()); + } }); Rng { rb: self } diff --git a/src/rtc.rs b/src/rtc.rs index dadb822c..36141317 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -4,7 +4,7 @@ use crate::bb; use crate::pac::rtc::{dr, tr}; -use crate::pac::{self, rcc::RegisterBlock, PWR, RCC, RTC}; +use crate::pac::{self, PWR, RCC, RTC}; use crate::rcc::Enable; use core::fmt; use fugit::RateExtU32; @@ -152,14 +152,14 @@ impl Rtc { // Enable write protect unsafe { - let rcc = &(*RCC::ptr()); + let mut rcc = RCC::steal(); // As per the sample code, unlock comes first. (Enable PWR and DBP) - result.unlock(rcc, pwr); + result.unlock(&mut rcc, pwr); match result.clock_source { ClockSource::Lse(mode) => { // If necessary, enable the LSE. if rcc.bdcr().read().lserdy().bit_is_clear() { - result.enable_lse(rcc, mode); + result.enable_lse(&mut rcc, mode); } // Set clock source to LSE. rcc.bdcr().modify(|_, w| w.rtcsel().lse()); @@ -167,13 +167,13 @@ impl Rtc { ClockSource::Lsi => { // If necessary, enable the LSE. if rcc.csr().read().lsirdy().bit_is_clear() { - result.enable_lsi(rcc); + result.enable_lsi(&mut rcc); } // Set clock source to LSI. rcc.bdcr().modify(|_, w| w.rtcsel().lsi()); } } - result.enable(rcc); + result.enable(&mut rcc); } result.modify(true, |regs| { @@ -191,7 +191,7 @@ impl Rtc { /// Enable the low frequency external oscillator. This is the only mode currently /// supported, to avoid exposing the `CR` and `CRS` registers. - fn enable_lse(&mut self, rcc: &RegisterBlock, mode: LSEClockMode) { + fn enable_lse(&mut self, rcc: &mut RCC, mode: LSEClockMode) { unsafe { // Force a reset of the backup domain. self.backup_reset(rcc); @@ -221,7 +221,7 @@ impl Rtc { Self::with_config(regs, pwr, ClockSource::Lsi, prediv_s, prediv_a) } - fn enable_lsi(&mut self, rcc: &RegisterBlock) { + fn enable_lsi(&mut self, rcc: &mut RCC) { // Force a reset of the backup domain. self.backup_reset(rcc); // Enable the LSI. @@ -229,16 +229,20 @@ impl Rtc { while rcc.csr().read().lsirdy().is_not_ready() {} } - fn unlock(&mut self, rcc: &RegisterBlock, pwr: &mut PWR) { + fn unlock(&mut self, rcc: &mut RCC, pwr: &mut PWR) { // Enable the backup interface // Set APB1 - Bit 28 (PWREN) PWR::enable(rcc); // Enable access to the backup registers - pwr.cr().modify(|_, w| w.dbp().set_bit()); + #[cfg(feature = "f4")] + let cr1 = pwr.cr(); + #[cfg(feature = "f7")] + let cr1 = pwr.cr1(); + cr1.modify(|_, w| w.dbp().set_bit()); } - fn backup_reset(&mut self, rcc: &RegisterBlock) { + fn backup_reset(&mut self, rcc: &mut RCC) { unsafe { // Set BDCR - Bit 16 (BDRST) bb::set(rcc.bdcr(), 16); @@ -247,7 +251,7 @@ impl Rtc { } } - fn enable(&mut self, rcc: &RegisterBlock) { + fn enable(&mut self, rcc: &mut RCC) { // Start the actual RTC. // Set BDCR - Bit 15 (RTCEN) unsafe { @@ -680,22 +684,34 @@ impl Rtc { self.modify(false, |regs| match event { Event::AlarmA => { exti.rtsr().modify(|_, w| w.tr17().enabled()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr17().set_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im17().set_bit()); regs.cr().modify(|_, w| w.alraie().set_bit()); } Event::AlarmB => { exti.rtsr().modify(|_, w| w.tr17().enabled()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr17().set_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im17().set_bit()); regs.cr().modify(|_, w| w.alrbie().set_bit()); } Event::Wakeup => { exti.rtsr().modify(|_, w| w.tr22().enabled()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr22().set_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im22().set_bit()); regs.cr().modify(|_, w| w.wutie().set_bit()); } Event::Timestamp => { exti.rtsr().modify(|_, w| w.tr21().enabled()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr21().set_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im21().set_bit()); regs.cr().modify(|_, w| w.tsie().set_bit()); } }); @@ -707,22 +723,34 @@ impl Rtc { self.modify(false, |regs| match event { Event::AlarmA => { regs.cr().modify(|_, w| w.alraie().clear_bit()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr17().clear_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im17().clear_bit()); exti.rtsr().modify(|_, w| w.tr17().disabled()); } Event::AlarmB => { regs.cr().modify(|_, w| w.alrbie().clear_bit()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr17().clear_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im17().clear_bit()); exti.rtsr().modify(|_, w| w.tr17().disabled()); } Event::Wakeup => { regs.cr().modify(|_, w| w.wutie().clear_bit()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr22().clear_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im22().clear_bit()); exti.rtsr().modify(|_, w| w.tr22().disabled()); } Event::Timestamp => { regs.cr().modify(|_, w| w.tsie().clear_bit()); + #[cfg(not(feature = "gpio-f72x"))] exti.imr().modify(|_, w| w.mr21().clear_bit()); + #[cfg(feature = "gpio-f72x")] + exti.imr().modify(|_, w| w.im21().clear_bit()); exti.rtsr().modify(|_, w| w.tr21().disabled()); } }); diff --git a/src/sai.rs b/src/sai.rs index 343f7fb6..17a1815b 100644 --- a/src/sai.rs +++ b/src/sai.rs @@ -31,7 +31,12 @@ use crate::pac::SAI2; feature = "stm32f439" ))] use crate::pac::{sai, SAI as SAI1}; -#[cfg(any(feature = "stm32f427", feature = "stm32f437", feature = "stm32f446"))] +#[cfg(any( + feature = "f7", + feature = "stm32f427", + feature = "stm32f437", + feature = "stm32f446" +))] use crate::pac::{sai1 as sai, SAI1}; use crate::rcc; use crate::time::Hertz; @@ -295,6 +300,8 @@ impl ChannelClocks for SAICH { } } +// TODO: f7 +#[cfg(feature = "f4")] #[cfg(feature = "sai2")] impl ChannelClocks for SAICH { fn get_clk_frequency(clocks: &rcc::Clocks) -> Option { @@ -302,6 +309,8 @@ impl ChannelClocks for SAICH { } } +// TODO: f7 +#[cfg(feature = "f4")] #[cfg(feature = "sai2")] impl ChannelClocks for SAICH { fn get_clk_frequency(clocks: &rcc::Clocks) -> Option { diff --git a/src/serial.rs b/src/serial.rs index 06256733..9714a4fb 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -60,6 +60,7 @@ pub enum Error { } /// UART interrupt events +#[cfg(feature = "uart_v2")] #[enumflags2::bitflags] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Eq, PartialEq, Copy, Clone)] @@ -77,7 +78,31 @@ pub enum Event { ParityError = 1 << 8, } +/// UART interrupt events +#[cfg(feature = "uart_v3")] +#[enumflags2::bitflags] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[repr(u32)] +pub enum Event { + /// IDLE interrupt enable + Idle = 1 << 4, + /// RXNE interrupt enable + RxNotEmpty = 1 << 5, + /// Transmission complete interrupt enable + TransmissionComplete = 1 << 6, + /// TXE interrupt enable + TxEmpty = 1 << 7, + /// PE interrupt enable + ParityError = 1 << 8, + /// Character match interrupt enable + CharacterMatch = 1 << 14, + /// End of Block interrupt enable + EndOfBlock = 1 << 27, +} + /// UART/USART status flags +#[cfg(feature = "uart_v2")] #[enumflags2::bitflags] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Eq, PartialEq, Copy, Clone)] @@ -102,10 +127,60 @@ pub enum Flag { /// LIN break detection flag LinBreak = 1 << 8, /// CTS flag - Cts = 1 << 9, + CtsInterrupt = 1 << 9, +} + +/// UART/USART status flags +#[enumflags2::bitflags] +#[cfg(feature = "uart_v3")] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[repr(u32)] +pub enum Flag { + /// Parity error + ParityError = 1 << 0, + /// Framing error + FramingError = 1 << 1, + /// Noise detected flag + Noise = 1 << 2, + /// Overrun error + Overrun = 1 << 3, + /// IDLE line detected + Idle = 1 << 4, + /// Read data register not empty + RxNotEmpty = 1 << 5, + /// Transmission complete + TransmissionComplete = 1 << 6, + /// Transmit data register empty + TxEmpty = 1 << 7, + /// LIN break detection flag + LinBreak = 1 << 8, + /// CTS interrupt + CtsInterrupt = 1 << 9, + /// CTS flag + CtsStatus = 1 << 10, + /// Receiver timeout + ReceiverTimeout = 1 << 11, + /// End of block + EndOfBlock = 1 << 12, + /// Auto baud rate error + AutoBaudRateError = 1 << 14, + /// Auto baud rate + AutoBaudRateFlag = 1 << 15, + /// Busy flag + Busy = 1 << 16, + /// Character match + CharacterMatch = 1 << 17, + /// Send break + SendBreak = 1 << 18, + /// Receiver wakeup from Mute mode + ReceiverWakeup = 1 << 19, + /// Transmit enable acknowledge + TransmitEnableAck = 1 << 21, } /// UART clearable flags +#[cfg(feature = "uart_v2")] #[enumflags2::bitflags] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Eq, PartialEq, Copy, Clone)] @@ -119,6 +194,37 @@ pub enum CFlag { LinBreak = 1 << 8, } +/// UART clearable flags +#[cfg(feature = "uart_v3")] +#[enumflags2::bitflags] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[repr(u32)] +pub enum CFlag { + /// Parity error + ParityError = 1 << 0, + /// Framing error + FramingError = 1 << 1, + /// Noise detected + Noise = 1 << 2, + /// Overrun error + Overrun = 1 << 3, + /// Idle line detected + Idle = 1 << 4, + /// Transmission complete + TransmissionComplete = 1 << 6, + /// LIN break detection flag + LinBreak = 1 << 8, + /// CTS interrupt + CtsInterrupt = 1 << 9, + /// Receiver timeout + ReceiverTimeout = 1 << 11, + /// End of block + EndOfBlock = 1 << 12, + /// Character match + CharacterMatch = 1 << 17, +} + pub mod config; pub use config::Config; @@ -143,8 +249,13 @@ pub trait Instance: { #[doc(hidden)] #[inline(always)] - fn peri_address() -> u32 { - unsafe { &*Self::ptr() }.peri_address() + fn tx_peri_address() -> u32 { + unsafe { &*Self::ptr() }.tx_peri_address() + } + #[doc(hidden)] + #[inline(always)] + fn rx_peri_address() -> u32 { + unsafe { &*Self::ptr() }.rx_peri_address() } } @@ -287,7 +398,7 @@ impl Serial { calculate_brr(pclk_freq, baud)? }; - uart.brr().write(|w| unsafe { w.bits(div as u16) }); + uart.brr().write(|w| unsafe { w.bits(div as _) }); // Reset other registers to disable advanced USART features uart.cr2().reset(); @@ -304,12 +415,22 @@ impl Serial { // Enable transmission and receiving // and configure frame + // M[1:0] are used to set data bits + // M[1:0] = 00: 1 Start bit, 8 data bits, n stop bits + // M[1:0] = 01: 1 Start bit, 9 data bits, n stop bits + // M[1:0] = 10: 1 Start bit, 7 data bits, n stop bits uart.cr1().write(|w| { w.ue().set_bit(); w.over8().bit(over8); w.te().set_bit(); w.re().set_bit(); + #[cfg(feature = "uart_v2")] w.m().bit(config.wordlength == WordLength::DataBits9); + #[cfg(feature = "uart_v3")] + { + w.m0().bit(config.wordlength == WordLength::DataBits9); + w.m1().bit(config.wordlength == WordLength::DataBits7); + } w.pce().bit(config.parity != Parity::ParityNone); w.ps().bit(config.parity == Parity::ParityOdd) }); @@ -398,12 +519,24 @@ macro_rules! halUsart { } pub(crate) use halUsart; +#[cfg(feature = "usart1")] halUsart! { pac::USART1, Serial1, Rx1, Tx1 } +#[cfg(feature = "usart2")] halUsart! { pac::USART2, Serial2, Rx2, Tx2 } -halUsart! { pac::USART6, Serial6, Rx6, Tx6 } - #[cfg(feature = "usart3")] halUsart! { pac::USART3, Serial3, Rx3, Tx3 } +#[cfg(feature = "usart4")] +halUsart! { pac::USART4, Serial4, Rx4, Tx4 } +#[cfg(feature = "usart5")] +halUsart! { pac::USART5, Serial5, Rx5, Tx5 } +#[cfg(feature = "usart6")] +halUsart! { pac::USART6, Serial6, Rx6, Tx6 } +#[cfg(feature = "usart7")] +halUsart! { pac::USART7, Serial7, Rx7, Tx7 } +#[cfg(feature = "usart8")] +halUsart! { pac::USART8, Serial8, Rx8, Tx8 } +#[cfg(feature = "usart10")] +halUsart! { pac::USART10, Serial10, Rx10, Tx10 } #[cfg(feature = "uart4")] macro_rules! halUart { @@ -707,7 +840,7 @@ impl Serial { unsafe impl PeriAddress for Rx { #[inline(always)] fn address(&self) -> u32 { - self.usart.peri_address() + self.usart.rx_peri_address() } type MemSize = u8; @@ -723,7 +856,7 @@ where unsafe impl PeriAddress for Tx { #[inline(always)] fn address(&self) -> u32 { - self.usart.peri_address() + self.usart.tx_peri_address() } type MemSize = u8; diff --git a/src/serial/config.rs b/src/serial/config.rs index 49804142..a7084d5c 100644 --- a/src/serial/config.rs +++ b/src/serial/config.rs @@ -4,6 +4,8 @@ use crate::time::U32Ext; #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum WordLength { + #[cfg(feature = "uart_v3")] + DataBits7, DataBits8, DataBits9, } diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 4d36c38b..26770882 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -594,7 +594,7 @@ where { #[inline(always)] fn address(&self) -> u32 { - ::peri_address() + ::rx_peri_address() } type MemSize = u8; @@ -606,7 +606,7 @@ where { #[inline(always)] fn address(&self) -> u32 { - ::peri_address() + ::tx_peri_address() } type MemSize = u8; diff --git a/src/serial/uart_impls.rs b/src/serial/uart_impls.rs index 34109cf9..4b24b263 100644 --- a/src/serial/uart_impls.rs +++ b/src/serial/uart_impls.rs @@ -1,5 +1,9 @@ +#[cfg(feature = "f4")] use crate::pacext::uart::{Cr3W, SrR, UartRB}; +#[cfg(feature = "f7")] +use crate::pacext::uart::UartRB; + use super::{config, config::IrdaMode, CFlag, Error, Event, Flag}; use enumflags2::BitFlags; @@ -10,9 +14,13 @@ pub trait RegisterBlockImpl: UartRB { fn read_u16(&self) -> nb::Result { // NOTE(unsafe) atomic read with no side effects + #[cfg(feature = "uart_v2")] let sr = self.sr().read(); + #[cfg(feature = "uart_v3")] + let sr = self.isr().read(); // Any error requires the dr to be read to clear + #[cfg(feature = "uart_v2")] if sr.pe().bit_is_set() || sr.fe().bit_is_set() || sr.nf().bit_is_set() @@ -21,17 +29,30 @@ pub trait RegisterBlockImpl: UartRB { self.dr().read(); } + #[cfg(feature = "uart_v3")] + let icr = self.icr(); Err(if sr.pe().bit_is_set() { + #[cfg(feature = "uart_v3")] + icr.write(|w| w.pecf().clear()); Error::Parity.into() } else if sr.fe().bit_is_set() { + #[cfg(feature = "uart_v3")] + icr.write(|w| w.fecf().clear()); Error::FrameFormat.into() } else if sr.nf().bit_is_set() { + #[cfg(feature = "uart_v3")] + icr.write(|w| w.ncf().clear()); Error::Noise.into() } else if sr.ore().bit_is_set() { + #[cfg(feature = "uart_v3")] + icr.write(|w| w.orecf().clear()); Error::Overrun.into() } else if sr.rxne().bit_is_set() { // NOTE(unsafe) atomic read from stateless register + #[cfg(feature = "uart_v2")] return Ok(self.dr().read().dr().bits()); + #[cfg(feature = "uart_v3")] + return Ok(self.rdr().read().rdr().bits()); } else { nb::Error::WouldBlock }) @@ -39,11 +60,17 @@ pub trait RegisterBlockImpl: UartRB { fn write_u16(&self, word: u16) -> nb::Result<(), Error> { // NOTE(unsafe) atomic read with no side effects + #[cfg(feature = "uart_v2")] let sr = self.sr().read(); + #[cfg(feature = "uart_v3")] + let sr = self.isr().read(); if sr.txe().bit_is_set() { // NOTE(unsafe) atomic write to stateless register + #[cfg(feature = "uart_v2")] self.dr().write(|w| w.dr().set(word)); + #[cfg(feature = "uart_v3")] + self.tdr().write(|w| w.tdr().set(word)); Ok(()) } else { Err(nb::Error::WouldBlock) @@ -64,7 +91,10 @@ pub trait RegisterBlockImpl: UartRB { fn flush(&self) -> nb::Result<(), Error> { // NOTE(unsafe) atomic read with no side effects + #[cfg(feature = "uart_v2")] let sr = self.sr().read(); + #[cfg(feature = "uart_v3")] + let sr = self.isr().read(); if sr.tc().bit_is_set() { Ok(()) @@ -109,7 +139,11 @@ pub trait RegisterBlockImpl: UartRB { // ISR #[inline(always)] fn flags(&self) -> BitFlags { - BitFlags::from_bits_truncate(self.sr().read().bits()) + #[cfg(feature = "uart_v2")] + let sr = self.sr().read(); + #[cfg(feature = "uart_v3")] + let sr = self.isr().read(); + BitFlags::from_bits_truncate(sr.bits()) } #[inline(always)] @@ -126,13 +160,21 @@ pub trait RegisterBlockImpl: UartRB { } #[inline(always)] fn clear_flags(&self, flags: BitFlags) { - self.sr() - .write(|w| unsafe { w.bits(0xffff & !flags.bits()) }); + #[cfg(feature = "uart_v2")] + self.sr().write(|w| unsafe { w.bits(!flags.bits()) }); + #[cfg(feature = "uart_v3")] + self.icr().write(|w| unsafe { w.bits(flags.bits()) }); } fn clear_idle_interrupt(&self) { - let _ = self.sr().read(); - let _ = self.dr().read(); + #[cfg(feature = "uart_v2")] + { + let _ = self.sr().read(); + let _ = self.dr().read(); + } + #[cfg(feature = "uart_v3")] + self.icr().write(|w| w.idlecf().clear_bit_by_one()); } + #[cfg(feature = "uart_v2")] fn check_and_clear_error_flags(&self) -> Result<(), Error> { let sr = self.sr().read(); let _ = self.dr().read(); @@ -149,6 +191,27 @@ pub trait RegisterBlockImpl: UartRB { Ok(()) } } + #[cfg(feature = "uart_v3")] + fn check_and_clear_error_flags(&self) -> Result<(), Error> { + let sr = self.isr().read(); + let icr = self.icr(); + + if sr.pe().bit_is_set() { + icr.write(|w| w.pecf().clear()); + Err(Error::Parity) + } else if sr.fe().bit_is_set() { + icr.write(|w| w.fecf().clear()); + Err(Error::FrameFormat) + } else if sr.nf().bit_is_set() { + icr.write(|w| w.ncf().clear()); + Err(Error::Noise) + } else if sr.ore().bit_is_set() { + icr.write(|w| w.orecf().clear()); + Err(Error::Overrun) + } else { + Ok(()) + } + } fn enable_error_interrupt_generation(&self) { self.cr3().modify(|_, w| w.eie().enabled()); } @@ -197,9 +260,30 @@ pub trait RegisterBlockImpl: UartRB { self.listen_event(Some(Event::TxEmpty.into()), None) } - // PeriAddress - fn peri_address(&self) -> u32 { - self.dr().as_ptr() as u32 + // PeriAddress for transfer data + #[inline(always)] + fn tx_peri_address(&self) -> u32 { + #[cfg(feature = "uart_v2")] + { + self.dr().as_ptr() as u32 + } + #[cfg(feature = "uart_v3")] + { + self.tdr().as_ptr() as u32 + } + } + + // PeriAddress for receive data + #[inline(always)] + fn rx_peri_address(&self) -> u32 { + #[cfg(feature = "uart_v2")] + { + self.dr().as_ptr() as u32 + } + #[cfg(feature = "uart_v3")] + { + self.rdr().as_ptr() as u32 + } } fn enable_dma(&self, dc: config::DmaConfig) { @@ -256,6 +340,7 @@ impl RegisterBlockImpl for crate::pac::usart1::RegisterBlock { } } +#[cfg(feature = "f4")] #[cfg(feature = "uart4")] impl RegisterBlockImpl for crate::pac::uart4::RegisterBlock { const IRDA: bool = false; diff --git a/src/signature.rs b/src/signature.rs index cc27a74a..2c320b19 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -30,7 +30,10 @@ pub struct Uid { y: u16, waf_lot: [u8; 8], } +#[cfg(feature = "f4")] define_ptr_type!(Uid, 0x1FFF_7A10); +#[cfg(feature = "f7")] +define_ptr_type!(Uid, 0x1FF0_F420); impl Uid { /// X coordinate on wafer @@ -52,13 +55,21 @@ impl Uid { pub fn lot_num(&self) -> &str { unsafe { from_utf8_unchecked(&self.waf_lot[1..]) } } + + /// As a byte array + pub fn as_bytes() -> &'static [u8; 12] { + unsafe { &*(Self::ptr() as *const _) } + } } /// Size of integrated flash #[derive(Debug)] #[repr(C)] pub struct FlashSize(u16); +#[cfg(feature = "f4")] define_ptr_type!(FlashSize, 0x1FFF_7A22); +#[cfg(feature = "f7")] +define_ptr_type!(FlashSize, 0x1FF0_F442); impl FlashSize { /// Read flash size in kilobytes @@ -76,7 +87,10 @@ impl FlashSize { #[derive(Debug)] #[repr(C)] pub struct VrefCal(u16); +#[cfg(feature = "f4")] define_ptr_type!(VrefCal, 0x1FFF_7A2A); +#[cfg(feature = "f7")] +define_ptr_type!(VrefCal, 0x1FF0_F44A); impl VrefCal { /// Read calibration value @@ -86,10 +100,14 @@ impl VrefCal { } /// A temperature reading taken at 30°C stored at the factory +#[cfg(any(feature = "f4", feature = "f7"))] #[derive(Debug)] #[repr(C)] pub struct VtempCal30(u16); +#[cfg(feature = "f4")] define_ptr_type!(VtempCal30, 0x1FFF_7A2C); +#[cfg(feature = "f7")] +define_ptr_type!(VtempCal30, 0x1FF0_F44C); impl VtempCal30 { /// Read calibration value @@ -102,7 +120,10 @@ impl VtempCal30 { #[derive(Debug)] #[repr(C)] pub struct VtempCal110(u16); +#[cfg(feature = "f4")] define_ptr_type!(VtempCal110, 0x1FFF_7A2E); +#[cfg(feature = "f7")] +define_ptr_type!(VtempCal110, 0x1FF0_F44E); impl VtempCal110 { /// Read calibration value diff --git a/src/spi.rs b/src/spi.rs index 99f8eae9..21e49161 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1,11 +1,16 @@ use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; -use crate::dma::traits::{DMASet, PeriAddress}; -use crate::dma::{MemoryToPeripheral, PeripheralToMemory}; +use crate::dma::{ + traits::{DMASet, PeriAddress}, + MemoryToPeripheral, PeripheralToMemory, +}; use crate::gpio::{self, NoPin}; use crate::pac; +#[cfg(feature = "spi_v2")] +use crate::pac::spi1::cr2; + /// Clock polarity #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Polarity { @@ -126,7 +131,12 @@ pub const TransferModeNormal: bool = false; pub const TransferModeBidi: bool = true; pub trait FrameSize: Copy + Default { + #[cfg(feature = "spi_v1")] const DFF: bool; + #[cfg(feature = "spi_v2")] + const FRXTH: cr2::FRXTH; + #[cfg(feature = "spi_v2")] + const DS: cr2::DS; #[doc(hidden)] fn read_data(spi: &spi1::RegisterBlock) -> Self; #[doc(hidden)] @@ -134,7 +144,12 @@ pub trait FrameSize: Copy + Default { } impl FrameSize for u8 { + #[cfg(feature = "spi_v1")] const DFF: bool = false; + #[cfg(feature = "spi_v2")] + const FRXTH: cr2::FRXTH = cr2::FRXTH::Quarter; + #[cfg(feature = "spi_v2")] + const DS: cr2::DS = cr2::DS::EightBit; fn read_data(spi: &spi1::RegisterBlock) -> Self { spi.dr8().read().dr().bits() } @@ -144,7 +159,12 @@ impl FrameSize for u8 { } impl FrameSize for u16 { + #[cfg(feature = "spi_v1")] const DFF: bool = true; + #[cfg(feature = "spi_v2")] + const FRXTH: cr2::FRXTH = cr2::FRXTH::Half; + #[cfg(feature = "spi_v2")] + const DS: cr2::DS = cr2::DS::SixteenBit; fn read_data(spi: &spi1::RegisterBlock) -> Self { spi.dr().read().dr().bits() } @@ -219,6 +239,16 @@ pub trait Instance: + rcc::BusClock + gpio::alt::SpiCommon { + #[doc(hidden)] + #[inline(always)] + fn rx_peri_address() -> u32 { + unsafe { &*Self::ptr() }.dr().as_ptr() as u32 + } + #[doc(hidden)] + #[inline(always)] + fn tx_peri_address() -> u32 { + unsafe { &*Self::ptr() }.dr().as_ptr() as u32 + } } // Implemented by all SPI instances @@ -231,19 +261,20 @@ macro_rules! spi { }; } +#[cfg(feature = "spi1")] spi! { pac::SPI1: Spi1, SpiSlave1 } +#[cfg(feature = "spi2")] +#[cfg(not(any(feature = "svd-f746", feature = "svd-f750", feature = "svd-f756",)))] spi! { pac::SPI2: Spi2, SpiSlave2 } - #[cfg(feature = "spi3")] +#[cfg(not(any(feature = "svd-f745", feature = "svd-f765")))] spi! { pac::SPI3: Spi3, SpiSlave3 } - #[cfg(feature = "spi4")] spi! { pac::SPI4: Spi4, SpiSlave4 } - #[cfg(feature = "spi5")] spi! { pac::SPI5: Spi5, SpiSlave5 } - #[cfg(feature = "spi6")] +#[cfg(not(any(feature = "svd-f745", feature = "svd-f765")))] spi! { pac::SPI6: Spi6, SpiSlave6 } pub trait SpiExt: Sized + Instance { @@ -369,11 +400,16 @@ impl SpiExt for SPI { impl Spi { pub fn init(self) -> Self { + #[cfg(feature = "spi_v2")] + self.spi + .cr2() + .modify(|_, w| w.frxth().variant(W::FRXTH).ds().variant(W::DS)); self.spi.cr1().modify(|_, w| { // bidimode: 2-line or 1-line unidirectional w.bidimode().bit(BIDI); w.bidioe().bit(BIDI); // data frame size + #[cfg(feature = "spi_v1")] w.dff().bit(W::DFF); // spe: enable the SPI bus w.spe().set_bit() @@ -385,11 +421,16 @@ impl Spi { impl SpiSlave { pub fn init(self) -> Self { + #[cfg(feature = "spi_v2")] + self.spi + .cr2() + .modify(|_, w| w.frxth().variant(W::FRXTH).ds().variant(W::DS)); self.spi.cr1().modify(|_, w| { // bidimode: 2-line or 1-line unidirectional w.bidimode().bit(BIDI); w.bidioe().bit(BIDI); // data frame size + #[cfg(feature = "spi_v1")] w.dff().bit(W::DFF); // spe: enable the SPI bus w.spe().set_bit() @@ -622,7 +663,7 @@ impl SpiSlave { } } -impl Spi { +impl Spi { /// Pre initializing the SPI bus. fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self { // disable SS output @@ -640,6 +681,11 @@ impl Spi { _ => 0b111, }; + #[cfg(feature = "spi_v2")] + self.spi + .cr2() + .modify(|_, w| w.frxth().variant(W::FRXTH).ds().variant(W::DS)); + self.spi.cr1().write(|w| { w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); w.cpol().bit(mode.polarity == Polarity::IdleHigh); @@ -654,16 +700,23 @@ impl Spi { w.ssi().set_bit(); w.rxonly().clear_bit(); // dff: 8 bit frames - w.dff().clear_bit() + #[cfg(feature = "spi_v1")] + w.dff().clear_bit(); + w }); self } } -impl SpiSlave { +impl SpiSlave { /// Pre initializing the SPI bus. fn pre_init(self, mode: Mode) -> Self { + #[cfg(feature = "spi_v2")] + self.spi + .cr2() + .modify(|_, w| w.frxth().variant(W::FRXTH).ds().variant(W::DS)); + self.spi.cr1().write(|w| { w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); w.cpol().bit(mode.polarity == Polarity::IdleHigh); @@ -678,7 +731,9 @@ impl SpiSlave { w.ssi().set_bit(); w.rxonly().clear_bit(); // dff: 8 bit frames - w.dff().clear_bit() + #[cfg(feature = "spi_v1")] + w.dff().clear_bit(); + w }); self @@ -926,7 +981,7 @@ impl DmaBuilder { unsafe impl PeriAddress for Rx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*SPI::ptr()).dr().as_ptr() as u32 } + SPI::rx_peri_address() } type MemSize = u8; @@ -940,7 +995,7 @@ unsafe impl DMASet PeriAddress for Tx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*SPI::ptr()).dr().as_ptr() as u32 } + SPI::tx_peri_address() } type MemSize = u8; diff --git a/src/timer.rs b/src/timer.rs index 89c425dc..51239bae 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -9,6 +9,7 @@ use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use enumflags2::BitFlags; +#[cfg(feature = "bb")] use crate::bb; use crate::pac; @@ -554,7 +555,14 @@ macro_rules! hal { fn enable_channel(c: u8, b: bool) { let tim = unsafe { &*<$TIM>::ptr() }; if c < Self::CH_NUMBER { + #[cfg(feature = "bb")] unsafe { bb::write(tim.ccer(), c*4, b); } + #[cfg(not(feature = "bb"))] + tim.ccer().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << c*4)) + } else { + w.bits(r.bits() & !(1 << c*4)) + }}); } } @@ -562,7 +570,15 @@ macro_rules! hal { fn set_channel_polarity(c: u8, p: Polarity) { let tim = unsafe { &*<$TIM>::ptr() }; if c < Self::CH_NUMBER { - unsafe { bb::write(tim.ccer(), c*4 + 1, p == Polarity::ActiveLow); } + let b = p == Polarity::ActiveLow; + #[cfg(feature = "bb")] + unsafe { bb::write(tim.ccer(), c*4 + 1, b); } + #[cfg(not(feature = "bb"))] + tim.ccer().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << (c*4 + 1))) + } else { + w.bits(r.bits() & !(1 << (c*4 + 1))) + }}); } } @@ -570,7 +586,15 @@ macro_rules! hal { fn set_nchannel_polarity(c: u8, p: Polarity) { let tim = unsafe { &*<$TIM>::ptr() }; if c < Self::COMP_CH_NUMBER { - unsafe { bb::write(tim.ccer(), c*4 + 3, p == Polarity::ActiveLow); } + let b = p == Polarity::ActiveLow; + #[cfg(feature = "bb")] + unsafe { bb::write(tim.ccer(), c*4 + 3, b); } + #[cfg(not(feature = "bb"))] + tim.ccer().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << (c*4 + 3))) + } else { + w.bits(r.bits() & !(1 << (c*4 + 3))) + }}); } } } @@ -581,7 +605,14 @@ macro_rules! hal { let $aoe = (); let tim = unsafe { &*<$TIM>::ptr() }; if c < Self::COMP_CH_NUMBER { + #[cfg(feature = "bb")] unsafe { bb::write(tim.ccer(), c*4 + 2, b); } + #[cfg(not(feature = "bb"))] + tim.ccer().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << (c*4 + 2))) + } else { + w.bits(r.bits() & !(1 << (c*4 + 2))) + }}); } } fn set_dtg_value(value: u8) { @@ -596,11 +627,27 @@ macro_rules! hal { let tim = unsafe { &*<$TIM>::ptr() }; if !comp { if c < Self::CH_NUMBER { - unsafe { bb::write(tim.cr2(), c*2 + 8, s == IdleState::Set); } + let b = s == IdleState::Set; + #[cfg(feature = "bb")] + unsafe { bb::write(tim.cr2(), c*2 + 8, b); } + #[cfg(not(feature = "bb"))] + tim.cr2().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << (c*2 + 8))) + } else { + w.bits(r.bits() & !(1 << (c*2 + 8))) + }}); } } else { if c < Self::COMP_CH_NUMBER { - unsafe { bb::write(tim.cr2(), c*2 + 9, s == IdleState::Set); } + let b = s == IdleState::Set; + #[cfg(feature = "bb")] + unsafe { bb::write(tim.cr2(), c*2 + 9, b); } + #[cfg(not(feature = "bb"))] + tim.cr2().modify(|r,w| unsafe { if b { + w.bits(r.bits() | (1 << (c*2 + 9))) + } else { + w.bits(r.bits() & !(1 << (c*2 + 9))) + }}); } } } diff --git a/tools/check.py b/tools/check.py index ff9b338d..5dcf66cd 100755 --- a/tools/check.py +++ b/tools/check.py @@ -30,7 +30,7 @@ def main(): features = ["{},usb_fs,can,i2s,fsmc_lcd,rtic1,defmt,stm32-fmc".format(x) for x in crate_info["features"].keys() - if x.startswith("stm32f4")] + if x.startswith("stm32f4") or x.startswith("stm32f7")] if 'size_check' in sys.argv: cargo_cmd = ['cargo', 'build', '--release']