From 4418fcab753b5e45307783858d42e0c3678eaac6 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 12 Jun 2024 12:13:25 +0300 Subject: [PATCH] merge f7xx-hal --- .github/workflows/ci.yml | 9 + .vscode/settings.json | 2 +- Cargo.toml | 750 +++++-- README.md | 32 +- build.rs | 4 +- examples/spi_16.rs | 60 + src/adc.rs | 8 + src/adc/f2.rs | 1 + src/adc/f4.rs | 4 +- src/adc/f7.rs | 63 + src/can.rs | 29 +- src/dma/traits.rs | 18 + src/dma/traits/f2.rs | 119 ++ src/dma/traits/f7.rs | 225 +++ src/{flash.rs => flash/f4.rs} | 0 src/flash/f7.rs | 301 +++ src/gpio.rs | 12 + src/gpio/alt.rs | 12 + src/gpio/alt/f2.rs | 1905 ++++++++++++++++++ src/gpio/alt/f7.rs | 3477 +++++++++++++++++++++++++++++++++ src/gpio/f2.rs | 181 ++ src/gpio/f7.rs | 605 ++++++ src/i2c.rs | 8 +- src/i2c/f7.rs | 546 ++++++ src/lib.rs | 100 +- src/ltdc.rs | 3 + src/otg_fs.rs | 1 + src/otg_hs.rs | 108 +- src/prelude.rs | 6 + src/rcc/f2/mod.rs | 1 + src/rcc/f7/enable.rs | 211 ++ src/rcc/f7/mod.rs | 1678 ++++++++++++++++ src/rcc/mod.rs | 12 + src/serial.rs | 24 +- src/serial/config.rs | 2 + src/serial/dma.rs | 4 +- src/serial/uart_impls.rs | 111 +- src/signature.rs | 21 + src/spi.rs | 70 +- src/timer.rs | 68 +- src/uart.rs | 8 +- tools/check.py | 2 +- 42 files changed, 10577 insertions(+), 224 deletions(-) create mode 100644 examples/spi_16.rs create mode 100644 src/adc/f2.rs create mode 100644 src/adc/f7.rs create mode 100644 src/dma/traits/f2.rs create mode 100644 src/dma/traits/f7.rs rename src/{flash.rs => flash/f4.rs} (100%) create mode 100644 src/flash/f7.rs create mode 100644 src/gpio/alt/f2.rs create mode 100644 src/gpio/alt/f7.rs create mode 100644 src/gpio/f2.rs create mode 100644 src/gpio/f7.rs create mode 100644 src/i2c/f7.rs create mode 100644 src/rcc/f2/mod.rs create mode 100644 src/rcc/f7/enable.rs create mode 100644 src/rcc/f7/mod.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8de97350e..3581414f9 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/.vscode/settings.json b/.vscode/settings.json index 2268655a8..d9fc00f0e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { "rust-analyzer.check.allTargets": false, "rust-analyzer.check.targets": "thumbv7em-none-eabihf", - "rust-analyzer.cargo.features": ["defmt", "rtic1", "stm32f411"] + "rust-analyzer.cargo.features": ["defmt", "rtic1", "stm32f746"] } diff --git a/Cargo.toml b/Cargo.toml index 6cb825d72..c2252fe17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,17 @@ micromath = { version = "2.1.0", optional = true } package = "stm32f4-staging" version = "0.16.0" features = ["defmt", "atomics"] +optional = true + +[dependencies.stm32f2] +git = "https://github.com/stm32-rs/stm32-rs-nightlies" +features = ["defmt", "atomics"] +optional = true + +[dependencies.stm32f7] +git = "https://github.com/stm32-rs/stm32-rs-nightlies" +features = ["defmt", "atomics"] +optional = true [dependencies.time] version = "0.3.14" @@ -122,6 +133,74 @@ default-features = false features = ["macros"] [features] +f2 = ["dep:stm32f2", "bb", "dma", "spi_v1", "uart_v2"] +f4 = ["dep:stm32f4", "bb", "dma", "spi_v1", "uart_v2"] +f7 = [ + "dep:stm32f7", + "dep:micromath", + "dep:stm32-fmc", + "dma", + "spi_v2", + "uart_v3", +] + +# F2 + +stm32f215 = ["svd-f215"] +stm32f217 = ["svd-f217"] + +svd-f215 = ["f2", "stm32f2?/stm32f215", "gpio-f217"] +svd-f217 = ["f2", "stm32f2?/stm32f217", "gpio-f217"] + + +gpio-f217 = [ + "can1", + "can2", + "dcmi", + "eth", + "fsmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "i2c2", + "i2c3", + "i2s", + "i2s2", + "i2s3", + "rtc", + "sdio", + "spi1", + "spi2", + "spi3", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim8", + "tim9", + "uart4", + "uart5", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", +] + +# F4 + #! Use one of the supported STM32-serie related features: #! `stm32f401`, `stm32f405`, `stm32f407`, `stm32f415`, `stm32f417`, `stm32f410`, #! `stm32f411`, `stm32f412`, `stm32f413`, `stm32f423`, `stm32f427`, `stm32f429`, @@ -129,89 +208,159 @@ 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"] -stm32f437 = ["stm32f4/stm32f427", "gpio-f427", "fsmc", "cryp"] -stm32f439 = ["stm32f4/stm32f429", "gpio-f427", "fmc", "cryp"] -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"] +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"] +svd-f446 = ["f4", "stm32f4?/stm32f446", "gpio-f446"] +svd-f469 = ["f4", "stm32f4?/stm32f469", "gpio-f469"] gpio-f401 = [ + "gpioc", "gpiod", "gpioe", + "i2c2", "i2c3", - "otg-fs", + "i2s", + "i2s2", + "i2s2ext", + "i2s3", + "i2s3ext", + "rtc", "sdio", + "spi1", + "spi2", "spi3", "spi4", + "sys", "tim1", + "tim10", + "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", - "tim10", - "tim11", + "usart1", + "usart2", + "usart6", ] gpio-f410 = [ - "dac", "fmpi2c1", + "gpioc", + "i2c2", + "i2s", + "i2s1", + "i2s2", + "i2s5", "lptim1", + "rtc", + "spi1", + "spi2", "spi5", + "sys", "tim1", + "tim11", "tim5", "tim6", "tim9", - "tim11", + "usart1", + "usart2", + "usart6", ] gpio-f411 = [ + "otg-fs", + "gpioc", "gpiod", - "gpioe", # "gpioi", + "gpioe", + "i2c2", "i2c3", - "otg-fs", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", + "rtc", "sdio", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "sys", "tim1", + "tim10", + "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", - "tim10", - "tim11", - "spi3", - "spi4", - "spi5", + "usart1", + "usart2", + "usart6", + ] gpio-f412 = [ - "gpiod", - "gpioe", - "gpiof", - "gpiog", + "otg-fs", + "rng", "can1", "can2", "dfsdm1", "fmpi2c1", "fsmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "i2c2", "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", "quadspi", - "otg-fs", - "rng", + "rtc", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", @@ -220,37 +369,52 @@ gpio-f412 = [ "tim7", "tim8", "tim9", - "tim10", - "tim11", - "tim12", - "tim13", - "tim14", + "usart1", + "usart2", "usart3", + "usart6", ] gpio-f413 = [ - "gpiod", - "gpioe", - "gpiof", - "gpiog", + "otg-fs", + "rng", + "aes", "can1", "can2", "can3", - "dac", "dfsdm1", "dfsdm2", - "fsmc", "fmpi2c1", + "fsmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "i2c2", "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "i2s4", + "i2s5", "lptim1", "quadspi", - "otg-fs", - "rng", + "rtc", "sai1", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", @@ -259,40 +423,51 @@ gpio-f413 = [ "tim7", "tim8", "tim9", - "tim10", - "tim11", - "tim12", - "tim13", - "tim14", - "usart3", + "uart10", "uart4", "uart5", "uart7", "uart8", "uart9", - "uart10", + "usart1", + "usart2", + "usart3", + "usart6", ] gpio-f417 = [ - "gpiod", - "gpioe", - "gpiof", - "gpiog", - "gpioi", "adc2", "adc3", + "otg-fs", + "otg-hs", + "rng", "can1", "can2", - "dac", "dcmi", - "eth", - "fsmc", + "eth", #"fsmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "i2c2", "i2c3", - "otg-fs", - "otg-hs", - "rng", + "i2s", + "i2s2", + "i2s3", + "rtc", "sdio", + "spi1", + "spi2", "spi3", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", @@ -301,43 +476,55 @@ gpio-f417 = [ "tim7", "tim8", "tim9", - "tim10", - "tim11", - "tim12", - "tim13", - "tim14", - "usart3", "uart4", "uart5", + "usart1", + "usart2", + "usart3", + "usart6", ] gpio-f427 = [ + "adc2", + "adc3", + "dma2d", + "otg-fs", + "otg-hs", + "rng", + "can1", + "can2", + "dcmi", + "eth", + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "gpioi", "gpioj", "gpiok", - "adc2", - "adc3", - "can1", - "can2", - "dac", - "dcmi", - "dma2d", - "eth", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s3", "ltdc", - "otg-fs", - "otg-hs", - "rng", + "rtc", "sai1", "sdio", + "spi1", + "spi2", "spi3", "spi4", "spi5", "spi6", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", @@ -346,41 +533,114 @@ gpio-f427 = [ "tim7", "tim8", "tim9", - "tim10", - "tim11", - "tim12", - "tim13", - "tim14", - "usart3", "uart4", "uart5", "uart7", "uart8", + "usart1", + "usart2", + "usart3", + "usart6", ] gpio-f446 = [ + "adc2", + "adc3", + "otg-fs", + "otg-hs", + "can1", + "can2", + "dcmi", + "fmc", + "fmpi2c1", + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "i2c2", + "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "quadspi", + "rtc", + "sai1", + "sai2", + "spdifrx", + "spi1", + "spi2", + "spi3", + "spi4", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim6", + "tim7", + "tim8", + "tim9", + "uart4", + "uart5", + "usart1", + "usart2", + "usart3", + "usart6", + "sdio", + +] +gpio-f469 = [ "adc2", "adc3", + "dma2d", + "otg-fs", + "otg-hs", + "rng", "can1", "can2", - "dac", "dcmi", - "fmpi2c1", + "dsihost", + "eth", "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "gpioj", + "gpiok", + "i2c2", "i2c3", + "i2s", + "i2s2", + "i2s3", + "ltdc", "quadspi", - "otg-fs", - "otg-hs", + "rtc", "sai1", - "sai2", "sdio", + "spi1", + "spi2", "spi3", "spi4", - "spdifrx", + "spi5", + "spi6", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", @@ -389,66 +649,234 @@ gpio-f446 = [ "tim7", "tim8", "tim9", + "uart4", + "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", +] + +# F7 + +stm32f722 = ["svd-f7x2"] +stm32f723 = ["svd-f7x3", "usb_hs_phy"] +stm32f730 = ["svd-f730", "usb_hs_phy"] +stm32f732 = ["svd-f7x2"] +stm32f733 = ["svd-f7x3", "usb_hs_phy"] +stm32f745 = ["svd-f745"] +stm32f746 = ["svd-f7x6"] +stm32f756 = ["svd-f7x6"] +stm32f765 = ["svd-f765"] +stm32f767 = ["svd-f7x7"] +stm32f769 = ["svd-f7x9"] +stm32f777 = ["svd-f7x7"] +stm32f778 = ["svd-f7x9"] +stm32f779 = ["svd-f7x9"] + +svd-f7x2 = ["f7", "stm32f7?/stm32f7x2", "gpio-f72x"] +svd-f7x3 = ["f7", "stm32f7?/stm32f7x3", "gpio-f72x"] +svd-f730 = ["f7", "stm32f7?/stm32f730", "gpio-f72x"] +svd-f745 = ["f7", "stm32f7?/stm32f745", "gpio-f746"] +svd-f7x6 = ["f7", "stm32f7?/stm32f7x6", "gpio-f746"] +svd-f765 = ["f7", "stm32f7?/stm32f765", "gpio-f76x"] +svd-f7x7 = ["f7", "stm32f7?/stm32f7x7", "gpio-f76x"] +svd-f7x9 = ["f7", "stm32f7?/stm32f7x9", "gpio-f76x"] + +gpio-f72x = [ + "adc2", + "adc3", + "aes", + "can1", + "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "i2c2", + "i2c3", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", + "quadspi", + "rtc", + "sai1", + "sai2", + "sdmmc1", + "sdmmc2", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "sys", + "tim1", "tim10", "tim11", "tim12", "tim13", "tim14", - "usart3", + "tim2", + "tim3", + "tim4", + "tim5", + "tim8", + "tim9", "uart4", "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", ] -gpio-f469 = [ +gpio-f746 = [ + "adc2", + "adc3", + "dma2d", + "can1", + "can2", + "cryp", + "dcmi", + "eth", + "fmc", + "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", + "gpioh", "gpioi", "gpioj", "gpiok", + "hash", + "i2c2", + "i2c3", + "i2c4", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", + "ltdc", + "quadspi", + "rtc", + "sai1", + "sai2", + "sdmmc1", + "spdifrx", + "spi1", + "spi2", + "spi3", + "spi4", + "spi5", + "spi6", + "sys", + "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", + "tim2", + "tim3", + "tim4", + "tim5", + "tim8", + "tim9", + "uart4", + "uart5", + "uart7", + "uart8", + "usart1", + "usart2", + "usart3", + "usart6", + "otg-fs", + "otg-hs", +] +gpio-f76x = [ "adc2", "adc3", + "dma2d", "can1", "can2", - "dac", - "dma2d", + "cryp", + "can3", "dcmi", + "dfsdm1", "dsihost", "eth", "fmc", + "gpioc", + "gpiod", + "gpioe", + "gpiof", + "gpiog", + "gpioh", + "gpioi", + "gpioj", + "gpiok", + "hash", + "i2c2", "i2c3", + "i2c4", + "i2s", + "i2s1", + "i2s2", + "i2s3", + "lptim1", "ltdc", + "mdios", "quadspi", - "otg-fs", - "otg-hs", - "rng", + "rtc", "sai1", - "sdio", + "sai2", + "sdmmc1", + "sdmmc2", + "spdifrx", + "spi1", + "spi2", "spi3", "spi4", "spi5", "spi6", + "sys", "tim1", + "tim10", + "tim11", + "tim12", + "tim13", + "tim14", "tim2", "tim3", "tim4", "tim5", - "tim6", - "tim7", "tim8", "tim9", - "tim10", - "tim11", - "tim12", - "tim13", - "tim14", - "usart3", "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"] @@ -486,48 +914,112 @@ fsmc_lcd = ["dep:display-interface", "dep:display-interface-04"] ## SDIO peripheral support. See [sdio-host](https://crates.io/crates/sdio-host) sdio-host = ["dep:sdio-host"] +bb = [] +dma = [] +spi_v1 = [] +spi_v2 = [] +uart_v2 = [] +uart_v3 = [] +usb_hs_phy = [] dfsdm = [] sai = [] adc2 = [] adc3 = [] +adf1 = [] aes = [] can1 = [] can2 = [] can3 = [] cryp = [] +cm4 = [] +crs1 = [] +comp1 = [] +comp2 = [] +comp3 = [] +comp4 = [] +comp5 = [] +comp6 = [] +comp7 = [] +crs = [] dac = [] dcmi = [] +debug = [] dfsdm1 = ["dfsdm"] dfsdm2 = ["dfsdm"] dma2d = [] dsihost = [] +hash = [] eth = [] +fdcan1 = [] +fdcan2 = [] +fdcan3 = [] fmc = [] fsmc = [] fmpi2c1 = [] +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 = [] +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 = [] @@ -542,13 +1034,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 @@ -563,7 +1081,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" @@ -642,7 +1160,7 @@ required-features = ["rng"] # stm32f407 [[example]] name = "rtc" -required-features = [] +required-features = ["f4"] [[example]] name = "rtc_alarm" @@ -716,6 +1234,10 @@ required-features = ["stm32f411"] name = "uart-dma" required-features = ["stm32f405"] +[[example]] +name = "spi_16" +required-features = ["gpiod"] + [[example]] name = "ssd1306-image" required-features = [] # stm32f411 @@ -755,3 +1277,5 @@ required-features = ["otg-fs", "usb_fs"] # stm32f401 [[example]] name = "ws2812-spi" required-features = [] +version = "0.3.14" +default-features = false diff --git a/README.md b/README.md index fe1f5c8ad..887b7e709 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 STM32F2/F4/F7 series microcontrollers. The selection of the MCU is done by feature gates, typically specified by board support crates. Currently supported configurations are: @@ -17,28 +17,50 @@ support crates. Currently supported configurations are: +* stm32f215 +* stm32f217 +* * 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 8e25570ea..d09e16319 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 000000000..fcd699793 --- /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 024dca703..7f87a1b96 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -140,8 +140,16 @@ use crate::{ use core::fmt; pub mod config; + +#[cfg(feature = "f2")] +mod f2; + +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f7")] +mod f7; + /// Vref internal signal, used for calibration pub struct Vref; diff --git a/src/adc/f2.rs b/src/adc/f2.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/adc/f2.rs @@ -0,0 +1 @@ + diff --git a/src/adc/f4.rs b/src/adc/f4.rs index f1d1cb1b0..87e56d145 100644 --- a/src/adc/f4.rs +++ b/src/adc/f4.rs @@ -12,7 +12,7 @@ adc_pins!( gpio::PA7 => (ADC1, 7), gpio::PB0 => (ADC1, 8), gpio::PB1 => (ADC1, 9), - Temperature => (ADC1, 16), + Temperature => (ADC1, 18), Vbat => (ADC1, 18), Vref => (ADC1, 17), ); @@ -205,7 +205,7 @@ adc_pins!( gpio::PA7 => (ADC1, 7), gpio::PB0 => (ADC1, 8), gpio::PB1 => (ADC1, 9), - Temperature => (ADC1, 16), + Temperature => (ADC1, 18), Vbat => (ADC1, 18), Vref => (ADC1, 17), ); diff --git a/src/adc/f7.rs b/src/adc/f7.rs new file mode 100644 index 000000000..dbb92163a --- /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!(pac::ADC1, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PA4 => 4, + gpio::PA5 => 5, + gpio::PA6 => 6, + gpio::PA7 => 7, + gpio::PB0 => 8, + gpio::PB1 => 9, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, + gpio::PC4 => 14, + gpio::PC5 => 15, + Temperature => 18, + Vbat => 18, + Vref => 17, +); + +adc_pins!(pac::ADC2, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PA4 => 4, + gpio::PA5 => 5, + gpio::PA6 => 6, + gpio::PA7 => 7, + gpio::PB0 => 8, + gpio::PB1 => 9, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, + gpio::PC4 => 14, + gpio::PC5 => 15, +); + +adc_pins!(pac::ADC3, + gpio::PA0 => 0, + gpio::PA1 => 1, + gpio::PA2 => 2, + gpio::PA3 => 3, + gpio::PF6 => 4, + gpio::PF7 => 5, + gpio::PF8 => 6, + gpio::PF9 => 7, + gpio::PF10 => 8, + gpio::PF3 => 9, + gpio::PC0 => 10, + gpio::PC1 => 11, + gpio::PC2 => 12, + gpio::PC3 => 13, + gpio::PF4 => 14, + gpio::PF5 => 15, +); diff --git a/src/can.rs b/src/can.rs index 44034f242..fd0c5a52f 100644 --- a/src/can.rs +++ b/src/can.rs @@ -2,7 +2,7 @@ //! use crate::gpio::{self, NoPin}; -use crate::pac::{CAN1, CAN2}; +use crate::pac; use crate::rcc; pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + gpio::alt::CanCommon {} @@ -16,22 +16,22 @@ macro_rules! can { } // Implemented by all SPI instances -can! { CAN1: Can1 } -can! { CAN2: Can2 } +can! { pac::CAN1: Can1 } +#[cfg(feature = "can2")] +can! { pac::CAN2: Can2 } #[cfg(feature = "can3")] -can! { crate::pac::CAN3: Can3 } +can! { pac::CAN3: Can3 } /// Pins and definitions for models with a third CAN peripheral #[cfg(feature = "can3")] mod can3 { use super::*; - use crate::pac::CAN3; - unsafe impl bxcan::Instance for Can { - const REGISTERS: *mut bxcan::RegisterBlock = CAN3::ptr() as *mut _; + unsafe impl bxcan::Instance for Can { + const REGISTERS: *mut bxcan::RegisterBlock = pac::CAN3::ptr() as *mut _; } - unsafe impl bxcan::FilterOwner for Can { + unsafe impl bxcan::FilterOwner for Can { const NUM_FILTER_BANKS: u8 = 14; } } @@ -110,16 +110,17 @@ impl Can { } } -unsafe impl bxcan::Instance for Can { - const REGISTERS: *mut bxcan::RegisterBlock = CAN1::ptr() as *mut _; +unsafe impl bxcan::Instance for Can { + const REGISTERS: *mut bxcan::RegisterBlock = pac::CAN1::ptr() as *mut _; } -unsafe impl bxcan::Instance for Can { - const REGISTERS: *mut bxcan::RegisterBlock = CAN2::ptr() as *mut _; +#[cfg(feature = "can2")] +unsafe impl bxcan::Instance for Can { + const REGISTERS: *mut bxcan::RegisterBlock = pac::CAN2::ptr() as *mut _; } -unsafe impl bxcan::FilterOwner for Can { +unsafe impl bxcan::FilterOwner for Can { const NUM_FILTER_BANKS: u8 = 28; } -unsafe impl bxcan::MasterInstance for Can {} +unsafe impl bxcan::MasterInstance for Can {} diff --git a/src/dma/traits.rs b/src/dma/traits.rs index 96e9ef718..84e10d97b 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. @@ -344,7 +346,23 @@ macro_rules! dma_map { } use dma_map; +#[cfg(feature = "f2")] +mod f2; +#[allow(unused)] +#[cfg(feature = "f2")] +pub use f2::*; + +#[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/f2.rs b/src/dma/traits/f2.rs new file mode 100644 index 000000000..73e176ed0 --- /dev/null +++ b/src/dma/traits/f2.rs @@ -0,0 +1,119 @@ +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 + (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 + + (Stream2:5, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH4 + (Stream2:5, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_UP + (Stream4:5, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH1 + (Stream4:5, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_TRIG + (Stream5:5, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH2 + (Stream7:5, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM3_CH3 + + (Stream0:6, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH3/UP + (Stream0:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH3/UP + (Stream1:6, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH4/TRIG + (Stream1:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH4/TRIG + (Stream2:6, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH1 + (Stream3:6, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM5_CH4/TRIG + (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 + (Stream2:0, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH1 + (Stream2:0, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH2 + (Stream2:0, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH3 + (Stream4:0, pac::ADC1, [PeripheralToMemory]), //ADC1 + (Stream6:0, timer::CCR1, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH1 + (Stream6:0, timer::CCR2, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH2 + (Stream6:0, timer::CCR3, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH3 + + (Stream1:1, pac::DCMI, [PeripheralToMemory]), //DCMI + (Stream2:1, pac::ADC2, [PeripheralToMemory]), //ADC2 + (Stream3:1, pac::ADC2, [PeripheralToMemory]), //ADC2 + (Stream7:1, pac::DCMI, [PeripheralToMemory]), //DCMI + + (Stream0:2, pac::ADC3, [PeripheralToMemory]), //ADC3 + (Stream1:2, pac::ADC3, [PeripheralToMemory]), //ADC3 + //(Stream7:2, pac::HASH_IN, [MemoryToPeripheral]), //HASH_IN + (Stream0:3, pac::SPI1, [PeripheralToMemory]), //SPI1_RX + (Stream2:3, pac::SPI1, [PeripheralToMemory]), //SPI1_RX + (Stream3:3, pac::SPI1, [MemoryToPeripheral]), //SPI1_TX + (Stream5:3, pac::SPI1, [MemoryToPeripheral]), //SPI1_TX + + (Stream2:4, pac::USART1, [PeripheralToMemory]), //USART1_RX + (Stream3:4, pac::SDIO, [MemoryToPeripheral | PeripheralToMemory]), //SDIO + (Stream5:4, pac::USART1, [PeripheralToMemory]), //USART1_RX + (Stream6:4, pac::SDIO, [MemoryToPeripheral | PeripheralToMemory]), //SDIO + (Stream7:4, pac::USART1, [MemoryToPeripheral]), //USART1_TX + + (Stream1:5, pac::USART6, [PeripheralToMemory]), //USART6_RX + (Stream2:5, pac::USART6, [PeripheralToMemory]), //USART6_RX + (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/TRIG/COM + (Stream4:6, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM1_CH4/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 + (Stream7:7, timer::CCR4, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_CH4 + (Stream7:7, timer::DMAR, [MemoryToPeripheral | PeripheralToMemory]), //TIM8_TRIG/COM +} + +#[cfg(feature = "cryp")] +dma_map! { + (Stream5:2, pac::CRYP_OUT, [PeripheralToMemory]), //CRYP_OUT + (Stream6:2, pac::CRYP_IN, [MemoryToPeripheral]), //CRYP_IN +} diff --git a/src/dma/traits/f7.rs b/src/dma/traits/f7.rs new file mode 100644 index 000000000..09670f445 --- /dev/null +++ b/src/dma/traits/f7.rs @@ -0,0 +1,225 @@ +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 = "gpio-f76x")] +#[cfg(not(feature = "stm32f765"))] +use crate::pac::DFSDM; +#[cfg(feature = "stm32f765")] +use crate::pac::DFSDM1 as DFSDM; +#[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: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 + + //(Stream0:9, FLT, [MemoryToPeripheral]), //JPEG_IN + //(Stream1:9, FLT, [PeripheralToMemory]), //JPEG_OUT + //(Stream3:9, FLT, [MemoryToPeripheral]), //JPEG_IN + //(Stream4:9, FLT, [PeripheralToMemory]), //JPEG_OUT + + (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 + +); 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 000000000..158707429 --- /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/gpio.rs b/src/gpio.rs index 2fa1a4a0e..6f76b7ea1 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -600,9 +600,21 @@ macro_rules! gpio { } use gpio; +#[cfg(feature = "f2")] +mod f2; +#[cfg(feature = "f2")] +pub use f2::*; + +#[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 83bb0978c..468de4eec 100644 --- a/src/gpio/alt.rs +++ b/src/gpio/alt.rs @@ -1,6 +1,18 @@ +#[cfg(feature = "f2")] +mod f2; +#[cfg(feature = "f2")] +pub use f2::*; + +#[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/f2.rs b/src/gpio/alt/f2.rs new file mode 100644 index 000000000..3528e0e37 --- /dev/null +++ b/src/gpio/alt/f2.rs @@ -0,0 +1,1905 @@ +use super::*; +use crate::gpio::{self, NoPin, OpenDrain, PushPull}; + +pub mod can1 { + use super::*; + + pin! { + for no:NoPin, [ + PA11<9>, + + PB8<9>, + + PD0<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; + } +} + +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; + } +} + +pub mod dcmi { + use super::*; + + pin! { + for [ + PA9<13>, + + PC6<13>, + + PH9<13>, + ], + + for [ + PA10<13>, + + PC7<13>, + + PH10<13>, + ], + + for [ + PB5<13>, + + PI3<13>, + ], + + for [ + PD2<13>, + + PH15<13>, + ], + + for [ + PF11<13>, + ], + + for [ + PG15<13>, + + PI0<13>, + ], + + for [ + PC8<13>, + + PE0<13>, + + PH11<13>, + ], + + for [ + PC9<13>, + + PE1<13>, + + PH12<13>, + ], + + for [ + PC11<13>, + + PE4<13>, + + PH14<13>, + ], + + for [ + PB6<13>, + + PI4<13>, + ], + + for [ + PB8<13>, + + PE5<13>, + + PI6<13>, + ], + + for [ + PB9<13>, + + PE6<13>, + + PI7<13>, + ], + + for [ + PC10<13>, + + PI1<13>, + ], + + for [ + PC12<13>, + + PI2<13>, + ], + + for [ + PA4<13>, + + PH8<13>, + ], + + for [ + PA6<13>, + ], + + for [ + PB7<13>, + + PI5<13>, + ], + } +} + +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::*; + + pin! { + for [ + PF0<12>, + ], + + for [ + PF1<12>, + ], + + for [ + PG0<12>, + ], + + for [ + PG1<12>, + ], + + for [ + PG2<12>, + ], + + for [ + PG3<12>, + ], + + for [ + PG4<12>, + ], + + for [ + PG5<12>, + ], + + for [ + PD11<12>, + ], + + for [ + PD12<12>, + ], + + for [ + PD13<12>, + ], + + for [ + PE3<12>, + ], + + for [ + PF2<12>, + ], + + for [ + PE4<12>, + ], + + for [ + PE5<12>, + ], + + for [ + PE6<12>, + ], + + for [ + PE2<12>, + ], + + for [ + PG13<12>, + ], + + for [ + PG14<12>, + ], + + for [ + PF3<12>, + ], + + for [ + PF4<12>, + ], + + for [ + PF5<12>, + ], + + for [ + PF12<12>, + ], + + for [ + PF13<12>, + ], + + for [ + PF14<12>, + ], + + for [ + PF15<12>, + ], + + for [ + PD12<12>, + ], + + for [ + PF9<12>, + ], + + for [ + PD11<12>, + ], + + for [ + PD3<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + PE13<12>, + ], + + for [ + PE14<12>, + ], + + for [ + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + PE9<12>, + ], + + for [ + PE10<12>, + ], + + for [ + PE11<12>, + ], + + for [ + PE12<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + PE13<12>, + ], + + for [ + PE14<12>, + ], + + for [ + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + PE9<12>, + ], + + for [ + PE10<12>, + ], + + for [ + PE11<12>, + ], + + for [ + PE12<12>, + ], + + for [ + PG6<12>, + ], + + for [ + PG7<12>, + ], + + for [ + PF10<12>, + ], + + for [ + PE0<12>, + ], + + for [ + PE1<12>, + ], + + for [ + PD7<12>, + ], + + for [ + PG9<12>, + ], + + for [ + PG10<12>, + ], + + for [ + PG11<12>, + ], + + for [ + PD7<12>, + ], + + for [ + PG9<12>, + ], + + for [ + PG10<12>, + ], + + for [ + PG12<12>, + ], + + for [ + PF6<12>, + ], + + for [ + PF8<12>, + ], + + for [ + PB7<12>, + ], + + for [ + PD4<12>, + ], + + for [ + PF7<12>, + ], + + for [ + PD6<12>, + ], + + for [ + PD5<12>, + ], + } +} + +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; + } +} + +pub mod i2s { + use super::*; + + pin! { + for [ + PC9<5>, + ], + } +} + +pub mod i2s2 { + use super::*; + + pin! { + for no:NoPin, [ + PC6<5>, + ], + + for [ + PB10<5>, + + PB13<5>, + + PI1<5>, + ], + + for [ + PB15<5>, + + PC3<5>, + + PI3<5>, + ], + + for [ + PB9<5>, + + PB12<5>, + + PI0<5>, + ], + } +} + +pub mod i2s3 { + use super::*; + + pin! { + for no:NoPin, [ + PC7<6>, + ], + + for [ + PB3<6>, + + PC10<6>, + ], + + for [ + PB5<6>, + + PC12<6>, + ], + + for [ + PA4<6>, + + PA15<6>, + ], + } +} + +pub mod rcc { + use super::*; + + pin! { + for [ + PA8<0>, + ], + + for [ + PC9<0>, + ], + + for [ + PC14<0>, + ], + + for [ + PC15<0>, + ], + + for [ + PH0<0>, + ], + + for [ + PH1<0>, + ], + } +} + +pub mod rtc { + use super::*; + + pin! { + for [ + PC13<0>, + ], + + for [ + PB15<0>, + ], + } +} + +pub mod sdio { + 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>, + ], + } +} + +pub mod spi1 { + use super::*; + + pin! { + for no:NoPin, [ + PA6<5>, + + PB4<5>, + ], + + for no:NoPin, [ + PA7<5>, + + PB5<5>, + ], + + for [ + PA4<5>, + + PA15<5>, + ], + + for no:NoPin, [ + PA5<5>, + + PB3<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>, + + PC3<5>, + + PI3<5>, + ], + + for [ + PB9<5>, + + PB12<5>, + + PI0<5>, + ], + + for no:NoPin, [ + PB10<5>, + + PB13<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, [ + PB5<6>, + + PC12<6>, + ], + + 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 sys { + use super::*; + + pin! { + for [ + PA14<0>, + ], + + for [ + PA15<0>, + ], + + for [ + PB3<0>, + ], + + for [ + PA13<0>, + ], + + for [ + PB4<0>, + ], + + for [ + PE2<0>, + ], + + for [ + PE3<0>, + ], + + for [ + PE4<0>, + ], + + for [ + PE5<0>, + ], + + for [ + PE6<0>, + ], + + for [ + PA0<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 [ + 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 [ + 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 uart4 { + use super::*; + + pin! { + default:PushPull for no:NoPin, [ + PA1<8>, + + PC11<8>, + ], + + default:PushPull for no:NoPin, [ + PA0<8>, + + PC10<8>, + ], + } + use crate::pac::UART4 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } +} + +pub mod uart5 { + use super::*; + + pin! { + default:PushPull for no:NoPin, [ + PD2<8>, + ], + + default:PushPull for no:NoPin, [ + PC12<8>, + ], + } + use crate::pac::UART5 as UART; + impl SerialAsync for UART { + type Rx = Rx; + type Tx = Tx; + } +} + +pub mod usart1 { + use super::*; + + pin! { + for [ + PA8<7>, + ], + + for [ + PA11<7>, + ], + + for [ + PA12<7>, + ], + } + + pin! { + default:PushPull for no:NoPin, [ + PA10<7>, + + PB7<7>, + ], + + default:PushPull for no:NoPin, [ + PA9<7>, + + PB6<7>, + ], + } + use crate::pac::USART1 as USART; + impl SerialAsync for USART { + type Rx = Rx; + type Tx = Tx; + } + impl SerialSync for USART { + type Ck = Ck; + } + impl SerialRs232 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>, + ], + } + + 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 SerialRs232 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>, + ], + } + + 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 SerialRs232 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>, + ], + } + + 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 SerialRs232 for USART { + 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>, + ], + + for [ + PA3<10>, + ], + + for [ + PB0<10>, + ], + + for [ + PB1<10>, + ], + + for [ + PB10<10>, + ], + + for [ + PB11<10>, + ], + + for [ + PB12<10>, + ], + + for [ + PB13<10>, + ], + + for [ + PB5<10>, + ], + + for [ + PC2<10>, + + PI11<10>, + ], + + for [ + PC3<10>, + + PH4<10>, + ], + + for [ + PC0<10>, + ], + + for [ + PB13<12>, + ], + } +} diff --git a/src/gpio/alt/f7.rs b/src/gpio/alt/f7.rs new file mode 100644 index 000000000..1e0f9b42b --- /dev/null +++ b/src/gpio/alt/f7.rs @@ -0,0 +1,3477 @@ +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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 = "gpio-f76x")] +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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 = "gpio-f76x")] +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 = "gpio-f76x")] +pub mod dsihost { + use super::*; + + pin! { + for [ + PB11<13>, + + PJ2<13>, + ], + } +} + +#[cfg(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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. +
default: PushPull for [ + PD11<12>, + PD12<12>, + PD13<12>, + PE2<12>, + PE3<12>, + PE4<12>, + PE5<12>, + PE6<12>, + PF0<12>, + PF1<12>, + PF2<12>, + PF3<12>, + PF4<12>, + PF5<12>, + PF12<12>, + PF13<12>, + PF14<12>, + PF15<12>, + PG0<12>, + PG1<12>, + PG2<12>, + PG3<12>, + PG4<12>, + PG5<12>, + PG13<12>, + ], + } + + pin! { + for [ + PF0<12>, + ], + + for [ + PF1<12>, + ], + + for [ + PF2<12>, + ], + + for [ + PF3<12>, + ], + + for [ + PF4<12>, + ], + + for [ + PF5<12>, + ], + + for [ + PF12<12>, + ], + + for [ + PF13<12>, + ], + + for [ + PF14<12>, + ], + + for [ + PF15<12>, + ], + + for [ + PG0<12>, + ], + + for [ + PG1<12>, + ], + + for [ + PG2<12>, + ], + + for [ + PG3<12>, + ], + + for [ + PG4<12>, + ], + + for [ + PG5<12>, + ], + + for [ + PD11<12>, + ], + + for [ + PD12<12>, + ], + + for [ + PD13<12>, + ], + + for [ + PE3<12>, + ], + + for [ + PE4<12>, + ], + + for [ + PE5<12>, + ], + + for [ + PE6<12>, + ], + + for [ + PE2<12>, + ], + + for [ + PG13<12>, + ], + + for [ + PG14<12>, + ], + + for [ + PD12<12>, + ], + + for [ + PG4<12>, + ], + + for [ + PG5<12>, + ], + + for [ + PD11<12>, + ], + + for [ + PD3<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + PE9<12>, + ], + + for [ + PE10<12>, + ], + + for [ + PE11<12>, + ], + + for [ + PE12<12>, + ], + + for [ + PE13<12>, + ], + + for [ + PE14<12>, + ], + + for [ + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PH8<12>, + ], + + for [ + PH9<12>, + ], + + for [ + PH10<12>, + ], + + for [ + PH11<12>, + ], + + for [ + PH12<12>, + ], + + for [ + PH13<12>, + ], + + for [ + PH14<12>, + ], + + for [ + PH15<12>, + ], + + for [ + PI0<12>, + ], + + for [ + PI1<12>, + ], + + for [ + PI2<12>, + ], + + for [ + PI3<12>, + ], + + for [ + PI6<12>, + ], + + for [ + PI7<12>, + ], + + for [ + PI9<12>, + ], + + for [ + PI10<12>, + ], + + for [ + PD14<12>, + ], + + for [ + PD15<12>, + ], + + for [ + PD0<12>, + ], + + for [ + PD1<12>, + ], + + for [ + PE7<12>, + ], + + for [ + PE8<12>, + ], + + for [ + PE9<12>, + ], + + for [ + PE10<12>, + ], + + for [ + PE11<12>, + ], + + for [ + PE12<12>, + ], + + for [ + PE13<12>, + ], + + for [ + PE14<12>, + ], + + for [ + PE15<12>, + ], + + for [ + PD8<12>, + ], + + for [ + PD9<12>, + ], + + for [ + PD10<12>, + ], + + for [ + PG7<12>, + + #[cfg(feature = "gpio-f72x")] + PG11<12>, + ], + + for [ + PE0<12>, + ], + + for [ + PE1<12>, + ], + + for [ + PI4<12>, + ], + + for [ + PI5<12>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC8<9>, + + PG9<12>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC7<9>, + + PD7<12>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC8<9>, + + PG9<12>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PG6<12>, + + PG10<12>, + ], + + for [ + PG12<12>, + ], + + for [ + PB7<12>, + ], + + for [ + PD4<12>, + ], + + for [ + #[cfg(feature = "gpio-f76x")] + PC6<9>, + + PD6<12>, + ], + + for [ + PD5<12>, + ], + + for [ + PC3<12>, + + PC5<12>, + + PH2<12>, + ], + + for [ + PB5<12>, + + PH7<12>, + ], + + for [ + PG8<12>, + ], + + for [ + PG15<12>, + ], + + for [ + PC2<12>, + + PC4<12>, + + PH3<12>, + ], + + for [ + PB6<12>, + + PH6<12>, + ], + + for [ + PF11<12>, + ], + + for [ + PA7<12>, + + PC0<12>, + + PH5<12>, + ], + } +} + +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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 = "gpio-f76x")] +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 [ + PE2<6>, + + #[cfg(feature = "gpio-f76x")] + PG7<6>, + ], + + for [ + 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; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + 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 [ + PE0<10>, + + PI4<10>, + ], + + for [ + 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; + pub struct ChannelA; + pub struct ChannelB; + impl SaiChannels for SAI { + type A = ChannelA; + type B = ChannelB; + } + impl SaiChannel for ChannelA { + type Fs = FsA; + type Mclk = MclkA; + type Sck = SckA; + type Sd = SdA; + } + impl SaiChannel for ChannelB { + 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(any(feature = "gpio-f72x", feature = "gpio-f76x"))] +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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(any(feature = "gpio-f746", feature = "gpio-f76x"))] +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 SerialRs232 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 SerialRs232 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 SerialRs232 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 SerialRs232 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 SerialRs232 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 SerialRs232 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 SerialRs232 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 SerialRs232 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>, + ], + + for [ + PA3<10>, + ], + + for [ + PB0<10>, + ], + + for [ + PB1<10>, + ], + + for [ + PB10<10>, + ], + + for [ + PB11<10>, + ], + + for [ + PB12<10>, + ], + + for [ + PB13<10>, + ], + + for [ + PB5<10>, + ], + + for [ + PC2<10>, + + PI11<10>, + ], + + for [ + PC3<10>, + + PH4<10>, + ], + + for [ + PC0<10>, + ], + } +} diff --git a/src/gpio/f2.rs b/src/gpio/f2.rs new file mode 100644 index 000000000..60ca10c01 --- /dev/null +++ b/src/gpio/f2.rs @@ -0,0 +1,181 @@ +// auto-generated using codegen +// STM32CubeMX DB release: DB.6.0.50 +pub use super::*; + +pub use super::Input as DefaultMode; + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOA, gpioa, PA, 'A', PAn, [ + PA0: (pa0, 0, [0, 1, 2, 3, 7, 8, 11]), + PA1: (pa1, 1, [1, 2, 7, 8, 11]), + PA2: (pa2, 2, [1, 2, 3, 7, 11]), + PA3: (pa3, 3, [1, 2, 3, 7, 10, 11]), + PA4: (pa4, 4, [5, 6, 7, 12, 13]), + PA5: (pa5, 5, [1, 3, 5, 10]), + PA6: (pa6, 6, [1, 2, 3, 5, 9, 13]), + PA7: (pa7, 7, [1, 2, 3, 5, 9, 11]), + PA8: (pa8, 8, [0, 1, 4, 7, 10]), + PA9: (pa9, 9, [1, 4, 7, 13]), + PA10: (pa10, 10, [1, 7, 10, 13]), + PA11: (pa11, 11, [1, 7, 9, 10]), + PA12: (pa12, 12, [1, 7, 9, 10]), + PA13: (pa13, 13, [0], super::Debugger), + PA14: (pa14, 14, [0], super::Debugger), + PA15: (pa15, 15, [0, 1, 5, 6], super::Debugger), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOB, gpiob, PB, 'B', PBn, [ + PB0: (pb0, 0, [1, 2, 3, 10, 11]), + PB1: (pb1, 1, [1, 2, 3, 10, 11]), + PB2: (pb2, 2, []), + PB3: (pb3, 3, [0, 1, 5, 6], super::Debugger), + PB4: (pb4, 4, [0, 2, 5, 6], super::Debugger), + PB5: (pb5, 5, [2, 4, 5, 6, 9, 10, 11, 13]), + PB6: (pb6, 6, [2, 4, 7, 9, 13]), + PB7: (pb7, 7, [2, 4, 7, 12, 13]), + PB8: (pb8, 8, [2, 3, 4, 9, 11, 12, 13]), + PB9: (pb9, 9, [2, 3, 4, 5, 9, 12, 13]), + PB10: (pb10, 10, [1, 4, 5, 7, 10, 11]), + PB11: (pb11, 11, [1, 4, 7, 10, 11]), + PB12: (pb12, 12, [1, 4, 5, 7, 9, 10, 11, 12]), + PB13: (pb13, 13, [1, 5, 7, 9, 10, 11, 12]), + PB14: (pb14, 14, [1, 3, 5, 7, 9, 12]), + PB15: (pb15, 15, [0, 1, 3, 5, 9, 12]), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOC, gpioc, PC, 'C', PCn, [ + PC0: (pc0, 0, [10]), + PC1: (pc1, 1, [11]), + PC2: (pc2, 2, [5, 10, 11]), + PC3: (pc3, 3, [5, 10, 11]), + PC4: (pc4, 4, [11]), + PC5: (pc5, 5, [11]), + PC6: (pc6, 6, [2, 3, 5, 8, 12, 13]), + PC7: (pc7, 7, [2, 3, 6, 8, 12, 13]), + PC8: (pc8, 8, [2, 3, 8, 12, 13]), + PC9: (pc9, 9, [0, 2, 3, 4, 5, 12, 13]), + PC10: (pc10, 10, [6, 7, 8, 12, 13]), + PC11: (pc11, 11, [6, 7, 8, 12, 13]), + PC12: (pc12, 12, [6, 7, 8, 12, 13]), + PC13: (pc13, 13, [0]), + PC14: (pc14, 14, [0]), + PC15: (pc15, 15, [0]), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOD, gpiod, PD, 'D', PDn, [ + PD0: (pd0, 0, [9, 12]), + PD1: (pd1, 1, [9, 12]), + PD2: (pd2, 2, [2, 8, 12, 13]), + PD3: (pd3, 3, [7, 12]), + PD4: (pd4, 4, [7, 12]), + PD5: (pd5, 5, [7, 12]), + PD6: (pd6, 6, [7, 12]), + PD7: (pd7, 7, [7, 12]), + PD8: (pd8, 8, [7, 12]), + PD9: (pd9, 9, [7, 12]), + PD10: (pd10, 10, [7, 12]), + PD11: (pd11, 11, [7, 12]), + PD12: (pd12, 12, [2, 7, 12]), + PD13: (pd13, 13, [2, 12]), + PD14: (pd14, 14, [2, 12]), + PD15: (pd15, 15, [2, 12]), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOE, gpioe, PE, 'E', PEn, [ + PE0: (pe0, 0, [2, 12, 13]), + PE1: (pe1, 1, [12, 13]), + PE2: (pe2, 2, [0, 11, 12]), + PE3: (pe3, 3, [0, 12]), + PE4: (pe4, 4, [0, 12, 13]), + PE5: (pe5, 5, [0, 3, 12, 13]), + PE6: (pe6, 6, [0, 3, 12, 13]), + PE7: (pe7, 7, [1, 12]), + PE8: (pe8, 8, [1, 12]), + PE9: (pe9, 9, [1, 12]), + PE10: (pe10, 10, [1, 12]), + PE11: (pe11, 11, [1, 12]), + PE12: (pe12, 12, [1, 12]), + PE13: (pe13, 13, [1, 12]), + PE14: (pe14, 14, [1, 12]), + PE15: (pe15, 15, [1, 12]), +]); + +#[cfg(feature = "gpio-f217")] +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, 12]), + PF7: (pf7, 7, [3, 12]), + PF8: (pf8, 8, [9, 12]), + PF9: (pf9, 9, [9, 12]), + PF10: (pf10, 10, [12]), + PF11: (pf11, 11, [13]), + PF12: (pf12, 12, [12]), + PF13: (pf13, 13, [12]), + PF14: (pf14, 14, [12]), + PF15: (pf15, 15, [12]), +]); + +#[cfg(feature = "gpio-f217")] +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]), + PG7: (pg7, 7, [8, 12]), + PG8: (pg8, 8, [8, 11]), + PG9: (pg9, 9, [8, 12]), + PG10: (pg10, 10, [12]), + PG11: (pg11, 11, [11, 12]), + PG12: (pg12, 12, [8, 12]), + PG13: (pg13, 13, [8, 11, 12]), + PG14: (pg14, 14, [8, 11, 12]), + PG15: (pg15, 15, [8, 13]), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOH, gpioh, PH, 'H', PHn, [ + PH0: (ph0, 0, [0]), + PH1: (ph1, 1, [0]), + PH2: (ph2, 2, [11]), + PH3: (ph3, 3, [11]), + PH4: (ph4, 4, [4, 10]), + PH5: (ph5, 5, [4]), + PH6: (ph6, 6, [4, 9, 11]), + PH7: (ph7, 7, [4, 11]), + PH8: (ph8, 8, [4, 13]), + PH9: (ph9, 9, [4, 9, 13]), + PH10: (ph10, 10, [2, 13]), + PH11: (ph11, 11, [2, 13]), + PH12: (ph12, 12, [2, 13]), + PH13: (ph13, 13, [3, 9]), + PH14: (ph14, 14, [3, 13]), + PH15: (ph15, 15, [3, 13]), +]); + +#[cfg(feature = "gpio-f217")] +gpio!(GPIOI, gpioi, PI, 'I', PIn, [ + PI0: (pi0, 0, [2, 5, 13]), + PI1: (pi1, 1, [5, 13]), + PI2: (pi2, 2, [3, 5, 13]), + PI3: (pi3, 3, [3, 5, 13]), + PI4: (pi4, 4, [3, 13]), + PI5: (pi5, 5, [3, 13]), + PI6: (pi6, 6, [3, 13]), + PI7: (pi7, 7, [3, 13]), + PI8: (pi8, 8, []), + PI9: (pi9, 9, [9]), + PI10: (pi10, 10, [11]), + PI11: (pi11, 11, [10]), +]); diff --git a/src/gpio/f7.rs b/src/gpio/f7.rs new file mode 100644 index 000000000..06ee95b21 --- /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 92c014ed2..df32f4e21 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -124,10 +124,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/f7.rs b/src/i2c/f7.rs new file mode 100644 index 000000000..1bfd40400 --- /dev/null +++ b/src/i2c/f7.rs @@ -0,0 +1,546 @@ +//! Inter-Integrated Circuit (I2C) bus +//! For now, only master mode is implemented + +// NB : this implementation started as a modified copy of https://github.com/stm32-rs/stm32f1xx-hal/blob/master/src/i2c.rs + +use crate::gpio; +use crate::hal_02::blocking::i2c::{Read, Write, WriteRead}; +use crate::pac::{self, DWT}; +use crate::rcc::{BusClock, Clocks, Enable, Reset}; +use core::ops::Deref; +use fugit::HertzU32 as Hertz; +use nb::Error::{Other, WouldBlock}; +use nb::{Error as NbError, Result as NbResult}; + +/// I2C error +#[derive(Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum Error { + /// Bus error + Bus, + /// Arbitration loss + Arbitration, + /// No ack received + Acknowledge, + /// Overrun/underrun + Overrun, + /// Bus is busy + Busy, + // Pec, // SMBUS mode only + // Timeout, // SMBUS mode only + // Alert, // SMBUS mode only +} + +/// SPI mode. The user should make sure that the requested frequency can be +/// generated considering the buses clocks. +#[derive(Debug, PartialEq)] +pub enum Mode { + Standard { frequency: Hertz }, + Fast { frequency: Hertz }, + FastPlus { frequency: Hertz }, + Custom { timing_r: u32 }, +} + +impl Mode { + pub fn standard(frequency: Hertz) -> Self { + Mode::Standard { frequency } + } + + pub fn fast(frequency: Hertz) -> Self { + Mode::Fast { frequency } + } + + pub fn fast_plus(frequency: Hertz) -> Self { + Mode::FastPlus { frequency } + } +} + +pub trait Instance: + crate::Sealed + + Deref + + BusClock + + Enable + + Reset + + gpio::alt::I2cCommon +{ +} + +// Implemented by all I2C instances +macro_rules! i2c { + ($I2C:ty: $I2c:ident) => { + pub type $I2c = I2c<$I2C>; + + impl Instance for $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 } + +/// I2C peripheral operating in master mode +pub struct I2c { + i2c: I2C, + pins: (I2C::Scl, I2C::Sda), + mode: Mode, + pclk: Hertz, +} + +/// embedded-hal compatible blocking I2C implementation +pub struct BlockingI2c { + nb: I2c, + data_timeout: u32, +} + +// hddat and vddat are removed because SDADEL is always going to be 0 in this implementation so +// condition is always met +struct I2cSpec { + freq_max: u32, + sudat_min: u32, + _lscl_min: u32, + _hscl_min: u32, + trise_max: u32, // in ns + _tfall_max: u32, +} + +#[derive(Debug)] +struct I2cTiming { + presc: u8, + scldel: u8, + sdadel: u8, + sclh: u8, + scll: u8, +} + +// everything is in nano seconds +const I2C_STANDARD_MODE_SPEC: I2cSpec = I2cSpec { + freq_max: 102400, + sudat_min: 250, + _lscl_min: 4700, + _hscl_min: 4000, + trise_max: 640, + _tfall_max: 20, +}; +const I2C_FAST_MODE_SPEC: I2cSpec = I2cSpec { + freq_max: 409600, + sudat_min: 100, + _lscl_min: 1300, + _hscl_min: 600, + trise_max: 250, + _tfall_max: 100, +}; + +const I2C_FAST_PLUS_MODE_SPEC: I2cSpec = I2cSpec { + freq_max: 1024000, + sudat_min: 50, + _lscl_min: 500, + _hscl_min: 260, + trise_max: 60, + _tfall_max: 100, +}; + +fn calculate_timing( + spec: I2cSpec, + i2c_freq: u32, + scl_freq: u32, + an_filter: bool, + dnf: u8, +) -> I2cTiming { + // This dependency is not used when `cargo test`ing. More info: + // https://docs.rs/micromath/1.1.1/micromath/index.html#unused-import-warnings-when-linking-std + #[cfg(not(test))] + use micromath::F32Ext as _; + + // frequency limit check + assert!(scl_freq <= spec.freq_max); + // T_sync or delay introduced in SCL + // generally it is 2-3 clock cycles + // t_sync + dnf delay + let t_dnf = (dnf) as f32 / i2c_freq as f32; + // if analog filter is enabled then it offer about 50 - 70 ns delay + let t_af: f32 = if an_filter { + 40.0 / 1_000_000_000f32 + } else { + 0.0 + }; + // t_sync = 2 to 3 * i2cclk + let t_sync = 2.0 / (i2c_freq as f32); + // fall or rise time + let t_fall: f32 = 50f32 / 1_000_000_000f32; + let t_rise: f32 = 60f32 / 1_000_000_000f32; + let t_delay = t_fall + t_rise + 2.0 * (t_dnf + t_af + t_sync); + // formula is like F_i2cclk/F/F_scl_clk = (scl_h+scl_l+2)*(Presc + 1) + // consider scl_l+scl_h is 256 max. but in that case clock should always + // be 50% duty cycle. lets consider scl_l+scl_h to be 128. so that it can + // be changed later + // (scl_l+scl_h+2)(presc +1 ) ==> as scl_width*presc ==F_i2cclk/F/F_scl_clk + let product: f32 = (1.0 - t_delay * (scl_freq as f32)) * (i2c_freq / scl_freq) as f32; + let scl_l: u8; + let scl_h: u8; + 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_f32 { + // TODO: should we panic or use minimum allowed frequancy + scl_l = 0x7fu8; + scl_h = 0x7fu8; + presc = 0xfu8; + } else { + // smaller the minimum devition less difference between expected vs + // actual scl clock + let mut min_deviation = 16f32; + // TODO: use duty cycle and based on that use precstart + let presc_start = (product / 512.0).ceil() as u8; + presc = presc_start; + for tmp_presc in presc_start..17 { + let deviation = product % tmp_presc as f32; + if min_deviation > deviation { + min_deviation = deviation; + presc = tmp_presc; + } + } + // now that we have optimal prescalar value. optimal scl_l and scl_h + // needs to be calculated + let scl_width = (product / presc as f32) as u16; // it will be always less than 256 + scl_h = (scl_width / 2 - 1) as u8; + scl_l = (scl_width - scl_h as u16 - 1) as u8; // This is to get max precision + presc -= 1; + } + let scldel: u8 = (((spec.trise_max + spec.sudat_min) as f32 / 1_000_000_000.0) + / ((presc + 1) as f32 / i2c_freq as f32) + - 1.0) + .ceil() as u8; + I2cTiming { + presc, + scldel, + sdadel: 0, + sclh: scl_h, + scll: scl_l, + } +} + +macro_rules! check_status_flag { + ($i2c:expr, $flag:ident, $status:ident) => {{ + let isr = $i2c.isr().read(); + + if isr.berr().bit_is_set() { + $i2c.icr().write(|w| w.berrcf().set_bit()); + Err(Other(Error::Bus)) + } else if isr.arlo().bit_is_set() { + $i2c.icr().write(|w| w.arlocf().set_bit()); + Err(Other(Error::Arbitration)) + } else if isr.nackf().bit_is_set() { + $i2c.icr() + .write(|w| w.stopcf().set_bit().nackcf().set_bit()); + Err(Other(Error::Acknowledge)) + } else if isr.ovr().bit_is_set() { + $i2c.icr().write(|w| w.stopcf().set_bit().ovrcf().set_bit()); + Err(Other(Error::Overrun)) + } else if isr.$flag().$status() { + Ok(()) + } else { + Err(WouldBlock) + } + }}; +} + +macro_rules! busy_wait { + ($nb_expr:expr, $exit_cond:expr) => {{ + loop { + let res = $nb_expr; + if res != Err(WouldBlock) { + break res; + } + if $exit_cond { + break res; + } + } + }}; +} + +macro_rules! busy_wait_cycles { + ($nb_expr:expr, $cycles:expr) => {{ + let started = DWT::cycle_count(); + let cycles = $cycles; + busy_wait!($nb_expr, DWT::cycle_count().wrapping_sub(started) >= cycles) + }}; +} + +impl I2c { + /// Configures the I2C peripheral to work in master mode + pub fn new( + i2c: I2C, + pins: (impl Into, impl Into), + mode: Mode, + clocks: &Clocks, + ) -> Self { + unsafe { + I2C::enable_unchecked(); + I2C::reset_unchecked(); + } + + let pclk = I2C::clock(clocks); + + let pins = (pins.0.into(), pins.1.into()); + + let mut i2c = I2c { + i2c, + pins, + mode, + pclk, + }; + i2c.init(); + i2c + } + + /// Initializes I2C as master. Configures I2C_PRESC, I2C_SCLDEL, + /// I2C_SDAEL, I2C_SCLH, I2C_SCLL + /// + /// For now, only standard mode is implemented + fn init(&mut self) { + // NOTE : operations are in float for better precision, + // STM32F7 usually have FPU and this runs only at + // initialization so the footprint of such heavy calculation + // occurs only once + // Disable I2C during configuration + self.i2c.cr1().write(|w| w.pe().disabled()); + + let an_filter: bool = self.i2c.cr1().read().anfoff().is_enabled(); + let dnf = self.i2c.cr1().read().dnf().bits(); + + let i2c_timingr: I2cTiming = match self.mode { + Mode::Standard { frequency } => calculate_timing( + I2C_STANDARD_MODE_SPEC, + self.pclk.raw(), + frequency.raw(), + an_filter, + dnf, + ), + Mode::Fast { frequency } => calculate_timing( + I2C_FAST_MODE_SPEC, + self.pclk.raw(), + frequency.raw(), + an_filter, + dnf, + ), + Mode::FastPlus { frequency } => calculate_timing( + I2C_FAST_PLUS_MODE_SPEC, + self.pclk.raw(), + frequency.raw(), + an_filter, + dnf, + ), + Mode::Custom { timing_r } => I2cTiming { + presc: ((timing_r & 0xf000_0000) >> 28) as u8, + scldel: ((timing_r & 0x00f0_0000) >> 20) as u8, + sdadel: ((timing_r & 0x000f_0000) >> 16) as u8, + sclh: ((timing_r & 0x0000_ff00) >> 8) as u8, + scll: (timing_r & 0x0000_00ff) as u8, + }, + }; + self.i2c.timingr().write(|w| { + w.presc().set(i2c_timingr.presc); + w.scll().set(i2c_timingr.scll); + w.sclh().set(i2c_timingr.sclh); + w.sdadel().set(i2c_timingr.sdadel); + w.scldel().set(i2c_timingr.scldel) + }); + + self.i2c.cr1().modify(|_, w| w.pe().enabled()); + } + + /// Perform an I2C software reset + #[allow(dead_code)] + fn reset(&mut self) { + self.i2c.cr1().write(|w| w.pe().disabled()); + // wait for disabled + while self.i2c.cr1().read().pe().is_enabled() {} + + // Re-enable + self.i2c.cr1().write(|w| w.pe().enabled()); + } + + /// Set (7-bit) slave address, bus direction (write or read), + /// generate START condition and set address. + /// + /// The user has to specify the number `n_bytes` of bytes to + /// read. The peripheral automatically waits for the bus to be + /// free before sending the START and address + /// + /// Data transfers of more than 255 bytes are not yet + /// supported, 10-bit slave address are not yet supported + fn start(&self, addr: u8, n_bytes: u8, read: bool, auto_stop: bool) { + self.i2c.cr2().write(|w| { + // Setup data + w.sadd().set(u16::from(addr << 1)); + w.add10().clear_bit(); + w.nbytes().set(n_bytes); + w.start().set_bit(); + + // Setup transfer direction + match read { + true => w.rd_wrn().read(), + false => w.rd_wrn().write(), + }; + + // setup auto-stop + match auto_stop { + true => w.autoend().automatic(), + false => w.autoend().software(), + } + }); + } + + /// Releases the I2C peripheral and associated pins + pub fn release(self) -> (I2C, (I2C::Scl, I2C::Sda)) { + (self.i2c, self.pins) + } +} + +impl BlockingI2c { + pub fn new( + i2c: I2C, + pins: (impl Into, impl Into), + mode: Mode, + clocks: &Clocks, + data_timeout_us: u32, + ) -> Self { + let sysclk_mhz = clocks.sysclk().to_MHz(); + BlockingI2c { + nb: I2c::new(i2c, pins, mode, clocks), + data_timeout: data_timeout_us * sysclk_mhz, + } + } + + /// Wait for a byte to be read and return it (ie for RXNE flag + /// to be set) + fn wait_byte_read(&self) -> NbResult { + // Wait until we have received something + busy_wait_cycles!( + check_status_flag!(self.nb.i2c, rxne, is_not_empty), + self.data_timeout + )?; + + Ok(self.nb.i2c.rxdr().read().rxdata().bits()) + } + + /// Wait the write data register to be empty (ie for TXIS flag + /// to be set) and write the byte to it + fn wait_byte_write(&self, byte: u8) -> NbResult<(), Error> { + // Wait until we are allowed to send data + // (START has been ACKed or last byte when through) + busy_wait_cycles!( + check_status_flag!(self.nb.i2c, txis, is_empty), + self.data_timeout + )?; + + // Put byte on the wire + self.nb.i2c.txdr().write(|w| w.txdata().set(byte)); + + Ok(()) + } + + /// Wait for any previous address sequence to end automatically. + fn wait_start(&self) { + while self.nb.i2c.cr2().read().start().bit_is_set() {} + } +} + +impl Write for BlockingI2c { + type Error = NbError; + + /// Write bytes to I2C. Currently, `bytes.len()` must be less or + /// equal than 255 + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + // TODO support transfers of more than 255 bytes + assert!(bytes.len() < 256 && !bytes.is_empty()); + + // Wait for any previous address sequence to end + // automatically. This could be up to 50% of a bus + // cycle (ie. up to 0.5/freq) + self.wait_start(); + + // Set START and prepare to send `bytes`. The + // START bit can be set even if the bus is BUSY or + // I2C is in slave mode. + self.nb.start(addr, bytes.len() as u8, false, true); + + for byte in bytes { + self.wait_byte_write(*byte)?; + } + // automatic STOP + + Ok(()) + } +} + +impl Read for BlockingI2c { + type Error = NbError; + + /// Reads enough bytes from slave with `address` to fill `buffer` + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + // TODO support transfers of more than 255 bytes + assert!(buffer.len() < 256 && !buffer.is_empty()); + + // Wait for any previous address sequence to end + // automatically. This could be up to 50% of a bus + // cycle (ie. up to 0.5/freq) + self.wait_start(); + + // Set START and prepare to receive bytes into + // `buffer`. The START bit can be set even if the bus + // is BUSY or I2C is in slave mode. + self.nb.start(addr, buffer.len() as u8, true, true); + + for byte in buffer { + *byte = self.wait_byte_read()?; + } + + // automatic STOP + + Ok(()) + } +} + +impl WriteRead for BlockingI2c { + type Error = NbError; + + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + // TODO support transfers of more than 255 bytes + assert!(bytes.len() < 256 && !bytes.is_empty()); + assert!(buffer.len() < 256 && !buffer.is_empty()); + + // Start and make sure we don't send STOP after the write + self.wait_start(); + self.nb.start(addr, bytes.len() as u8, false, false); + + for byte in bytes { + self.wait_byte_write(*byte)?; + } + + // Wait until the write finishes before beginning to read. + // busy_wait2!(self.nb.i2c, tc, is_complete); + busy_wait_cycles!( + check_status_flag!(self.nb.i2c, tc, is_complete), + self.data_timeout + )?; + + // reSTART and prepare to receive bytes into `buffer` + self.nb.start(addr, buffer.len() as u8, true, true); + + for byte in buffer { + *byte = self.wait_byte_read()?; + } + // automatic STOP + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index ac8f7f500..2b7ae5d8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,73 +13,79 @@ pub use embedded_hal_02 as hal_02; pub use nb; pub use nb::block; -#[cfg(feature = "stm32f401")] +#[cfg(feature = "svd-f215")] +pub use stm32f2::stm32f215 as pac; + +#[cfg(feature = "svd-f217")] +pub use stm32f2::stm32f217 as pac; + +#[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. -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. -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. +#[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 = "stm32f439")] -/// 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 = "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-f7x2")] +pub use stm32f7::stm32f7x2 as pac; + +#[cfg(feature = "svd-f7x3")] +pub use stm32f7::stm32f7x3 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-f7x6")] +pub use stm32f7::stm32f7x6 as pac; + +#[cfg(feature = "svd-f765")] +pub use stm32f7::stm32f765 as pac; + +#[cfg(feature = "svd-f7x7")] +pub use stm32f7::stm32f7x7 as pac; + +#[cfg(feature = "svd-f7x9")] +pub use stm32f7::stm32f7x9 as pac; // Enable use of interrupt macro pub use crate::pac::interrupt; @@ -88,27 +94,40 @@ 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 = "f4")] pub mod i2c; +#[cfg(feature = "f7")] +#[path = "i2c/f7.rs"] +pub mod i2c; +#[cfg(feature = "f4")] pub mod i2s; #[cfg(all(feature = "usb_fs", feature = "otg-fs"))] pub mod otg_fs; #[cfg(all(any(feature = "usb_hs", docsrs), feature = "otg-hs"))] pub mod otg_hs; +#[cfg(feature = "f4")] #[cfg(feature = "rng")] pub mod rng; pub mod dma; 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")] +#[cfg(feature = "f7")] pub mod fmc; #[cfg(all(feature = "fsmc_lcd", any(feature = "fmc", feature = "fsmc")))] pub mod fsmc_lcd; @@ -119,6 +138,7 @@ pub mod qei; #[cfg(feature = "quadspi")] pub mod qspi; pub mod rcc; +#[cfg(feature = "f4")] pub mod rtc; #[cfg(all(feature = "sdio-host", feature = "sdio"))] pub mod sdio; diff --git a/src/ltdc.rs b/src/ltdc.rs index 4f5d5d0c3..d877704b2 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 92937e94a..075cd121d 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 f62a603b5..2482b5476 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,14 @@ pub struct USB { pub pin_dm: alt::Dm, pub pin_dp: alt::Dp, pub hclk: Hertz, + #[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 +41,37 @@ 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(|| 0.Hz()), + } + } + + #[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: (PB14>, PB15>), + clocks: &Clocks, + ) -> Self { + Self { + usb_global, + usb_device, + usb_pwrclk, + usb_phy: Some(usb_phy), + pin_dm: pins.0, + pin_dp: pins.1, + hclk: pac::OTG_HS_GLOBAL::clock(clocks), + hse: clocks.hse().expect("HSE should be enabled"), } } } @@ -51,16 +86,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 +110,58 @@ 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/prelude.rs b/src/prelude.rs index bc5e65ca1..926a4a1a5 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -58,11 +58,17 @@ pub use crate::dma::traits::StreamISR 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; +#[cfg(feature = "f4")] 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/f2/mod.rs b/src/rcc/f2/mod.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/rcc/f2/mod.rs @@ -0,0 +1 @@ + diff --git a/src/rcc/f7/enable.rs b/src/rcc/f7/enable.rs new file mode 100644 index 000000000..9abe34b6d --- /dev/null +++ b/src/rcc/f7/enable.rs @@ -0,0 +1,211 @@ +use super::*; + +macro_rules! bus_enable { + ($PER:ident => $en:ident) => { + impl Enable for crate::pac::$PER { + #[inline(always)] + fn enable(bus: &mut Self::Bus) { + bus.enr().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(bus: &mut Self::Bus) { + bus.enr().modify(|_, w| w.$en().clear_bit()); + } + #[inline(always)] + fn is_enabled() -> bool { + Self::Bus::new().enr().read().$en().bit_is_set() + } + #[inline(always)] + unsafe fn enable_unchecked() { + Self::enable(&mut Self::Bus::new()); + } + #[inline(always)] + unsafe fn disable_unchecked() { + Self::disable(&mut Self::Bus::new()); + } + } + }; +} + +macro_rules! bus_lpenable { + ($PER:ident => $lpen:ident) => { + impl LPEnable for crate::pac::$PER { + #[inline(always)] + fn low_power_enable(bus: &mut Self::Bus) { + bus.lpenr().modify(|_, w| w.$lpen().set_bit()); + // Stall the pipeline to work around erratum 2.1.13 (DM00037591) + cortex_m::asm::dsb(); + } + #[inline(always)] + fn low_power_disable(bus: &mut Self::Bus) { + bus.lpenr().modify(|_, w| w.$lpen().clear_bit()); + } + #[inline(always)] + fn is_low_power_enabled() -> bool { + Self::Bus::new().lpenr().read().$lpen().bit_is_set() + } + #[inline(always)] + unsafe fn low_power_enable_unchecked() { + Self::enable(&mut Self::Bus::new()); + } + #[inline(always)] + unsafe fn low_power_disable_unchecked() { + Self::disable(&mut Self::Bus::new()); + } + } + }; +} +macro_rules! bus_reset { + ($PER:ident => $rst:ident) => { + impl Reset for crate::pac::$PER { + #[inline(always)] + fn reset(bus: &mut Self::Bus) { + bus.rstr().modify(|_, w| w.$rst().set_bit()); + bus.rstr().modify(|_, w| w.$rst().clear_bit()); + } + #[inline(always)] + unsafe fn reset_unchecked() { + Self::reset(&mut Self::Bus::new()); + } + } + }; +} + +macro_rules! bus { + ($($PER:ident => ($busX:ty, $($en:ident)?, $($lpen:ident)?, $($rst:ident)?),)+) => { + $( + impl crate::Sealed for crate::pac::$PER {} + impl RccBus for crate::pac::$PER { + type Bus = $busX; + } + $(bus_enable!($PER => $en);)? + $(bus_lpenable!($PER => $lpen);)? + $(bus_reset!($PER => $rst);)? + )+ + }; +} + +// Peripherals respective buses +// TODO: check which processor has which peripheral and add them +bus! { + GPIOA => (AHB1, gpioaen, gpioalpen, gpioarst), // 0 + GPIOB => (AHB1, gpioben, gpioblpen, gpiobrst), // 1 + GPIOC => (AHB1, gpiocen, gpioclpen, gpiocrst), // 2 + GPIOD => (AHB1, gpioden, gpiodlpen, gpiodrst), // 3 + GPIOE => (AHB1, gpioeen, gpioelpen, gpioerst), // 4 + GPIOF => (AHB1, gpiofen, gpioflpen, gpiofrst), // 5 + GPIOG => (AHB1, gpiogen, gpioglpen, gpiogrst), // 6 + GPIOH => (AHB1, gpiohen, gpiohlpen, gpiohrst), // 7 + GPIOI => (AHB1, gpioien, gpioilpen, gpioirst), // 8 + CRC => (AHB1, crcen, crclpen, crcrst), // 12 + DMA1 => (AHB1, dma1en, dma1lpen, dma1rst), // 21 + DMA2 => (AHB1, dma2en, dma2lpen, dma2rst), // 22 + OTG_HS_GLOBAL => (AHB1, otghsen, otghslpen, otghsrst), // 29 + + RNG => (AHB2, rngen, rnglpen, rngrst), // 6 + OTG_FS_GLOBAL => (AHB2, otgfsen, otgfslpen, otgfsrst), // 7 + + FMC => (AHB3, fmcen, fmclpen, fmcrst), // 0 + QUADSPI => (AHB3, qspien, qspilpen, qspirst), // 1 + + TIM2 => (APB1, tim2en, tim2lpen, tim2rst), // 0 + TIM3 => (APB1, tim3en, tim3lpen, tim3rst), // 1 + TIM4 => (APB1, tim4en, tim4lpen, tim4rst), // 2 + TIM5 => (APB1, tim5en, tim5lpen, tim5rst), // 3 + TIM6 => (APB1, tim6en, tim6lpen, tim6rst), // 4 + TIM7 => (APB1, tim7en, tim7lpen, tim7rst), // 5 + TIM12 => (APB1, tim12en, tim12lpen, tim12rst), // 6 + TIM13 => (APB1, tim13en, tim13lpen, tim13rst), // 7 + TIM14 => (APB1, tim14en, tim14lpen, tim14rst), // 8 + LPTIM1 => (APB1, lptim1en, lptim1lpen, lptim1rst), // 9 + WWDG => (APB1, wwdgen, wwdglpen, wwdgrst), // 11 + SPI2 => (APB1, spi2en, spi2lpen, spi2rst), // 14 + SPI3 => (APB1, spi3en, spi3lpen, spi3rst), // 15 + USART2 => (APB1, usart2en, usart2lpen, usart2rst), // 17 + USART3 => (APB1, usart3en, usart3lpen, usart3rst), // 18 + UART4 => (APB1, uart4en, uart4lpen, uart4rst), // 19 + UART5 => (APB1, uart5en, uart5lpen, uart5rst), // 20 + I2C1 => (APB1, i2c1en, i2c1lpen, i2c1rst), // 21 + I2C2 => (APB1, i2c2en, i2c2lpen, i2c2rst), // 22 + I2C3 => (APB1, i2c3en, i2c3lpen, i2c3rst), // 23 + CAN1 => (APB1, can1en, can1lpen, can1rst), // 25 + PWR => (APB1, pwren, pwrlpen, pwrrst), // 28 + DAC => (APB1, dacen, daclpen, dacrst), // 29 + UART7 => (APB1, uart7en, uart7lpen, uart7rst), // 30 + UART8 => (APB1, uart8en, uart8lpen, uart8rst), // 31 + + TIM1 => (APB2, tim1en, tim1lpen, tim1rst), // 0 + TIM8 => (APB2, tim8en, tim8lpen, tim8rst), // 1 + USART1 => (APB2, usart1en, usart1lpen, usart1rst), // 4 + USART6 => (APB2, usart6en, usart6lpen, usart6rst), // 5 + ADC1 => (APB2, adc1en, adc1lpen, adcrst), // 8 + ADC2 => (APB2, adc2en, adc2lpen, adcrst), // 9 + ADC3 => (APB2, adc3en, adc3lpen, adcrst), // 10 + SDMMC1 => (APB2, sdmmc1en, sdmmc1lpen, sdmmc1rst), // 11 + SPI1 => (APB2, spi1en, spi1lpen, spi1rst), // 12 + SPI4 => (APB2, spi4en, spi4lpen, spi4rst), // 13 + SYSCFG => (APB2, syscfgen, syscfglpen, syscfgrst), // 14 + TIM9 => (APB2, tim9en, tim9lpen, tim9rst), // 16 + TIM10 => (APB2, tim10en, tim10lpen, tim10rst), // 17 + TIM11 => (APB2, tim11en, tim11lpen, tim11rst), // 18 + SPI5 => (APB2, spi5en, spi5lpen, spi5rst), // 20 + SAI1 => (APB2, sai1en, sai1lpen, sai1rst), // 22 + SAI2 => (APB2, sai2en, sai2lpen, sai2rst), // 23 +} + +#[cfg(any(feature = "svd-f730", feature = "svd-f7x2", feature = "svd-f7x3",))] +bus! { + AES => (AHB2, aesen, aeslpen, aesrst), // 4 + + SDMMC2 => (APB2, sdmmc2en, sdmmc2lpen, sdmmc2rst), // 7 + USBPHYC => (APB2, usbphycen,, usbphycrst), // 31 +} + +#[cfg(any( + feature = "svd-f745", + feature = "svd-f750", + feature = "svd-f7x6", + feature = "svd-f765", + feature = "svd-f7x7", + feature = "svd-f7x9", +))] +bus! { + GPIOJ => (AHB1, gpiojen, gpiojlpen, gpiojrst), // 9 + GPIOK => (AHB1, gpioken, gpioklpen, gpiokrst), // 10 + DMA2D => (AHB1, dma2den, dma2dlpen, dma2drst), // 23 + ETHERNET_MAC => (AHB1, ethmacen, ethmaclpen, ethmacrst), // 25 + + DCMI => (AHB2, dcmien, dcmilpen, dcmirst), // 0 + CRYP => (AHB2, crypen, cryplpen, cryprst), // 4 + HASH => (AHB2, hashen, hashlpen,), // 5 + + SPDIFRX => (APB1, spdifrxen, spdifrxlpen, spdifrxrst), // 16 + I2C4 => (APB1, i2c4en, i2c4lpen, i2c4rst), // 24 + CAN2 => (APB1, can2en, can2lpen, can2rst), // 26 + CEC => (APB1, cecen, ceclpen, cecrst), // 27 + + SPI6 => (APB2, spi6en, spi6lpen, spi6rst), // 21 + LTDC => (APB2, ltdcen, ltdclpen, ltdcrst), // 26 +} + +#[cfg(any(feature = "svd-f765", feature = "svd-f7x7", feature = "svd-f7x9"))] +bus! { + JPEG => (AHB2, jpegen, jpeglpen,), // 1 + + CAN3 => (APB1, can3en, can3lpen, can3rst), // 13 + + DSI => (APB2, dsien, dsilpen, dsirst), // 27 + MDIOS => (APB2, mdioen, mdiolpen, mdiorst), // 30 +} + +#[cfg(any(feature = "svd-f7x9", feature = "svd-f7x9"))] +bus! { + DFSDM => (APB2, dfsdm1en, dfsdm1lpen, dfsdm1rst), // 29 +} + +#[cfg(feature = "svd-f765")] +bus! { + DFSDM1 => (APB2, dfsdm1en, dfsdm1lpen, dfsdm1rst), // 29 +} diff --git a/src/rcc/f7/mod.rs b/src/rcc/f7/mod.rs new file mode 100644 index 000000000..8bacf45c8 --- /dev/null +++ b/src/rcc/f7/mod.rs @@ -0,0 +1,1678 @@ +//! Reset and clock control. + +use core::cmp::min; + +mod enable; + +use super::{BusClock, BusTimerClock, RccBus}; + +#[cfg_attr(test, allow(unused_imports))] +use micromath::F32Ext; + +use crate::pac::{rcc, 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); + +/// Extension trait that constrains the `RCC` peripheral +pub trait RccExt { + /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions + fn constrain(self) -> Rcc; +} + +impl RccExt for RCC { + fn constrain(self) -> Rcc { + Rcc { + ahb1: AHB1::new(), + ahb2: AHB2::new(), + ahb3: AHB3::new(), + apb1: APB1::new(), + apb2: APB2::new(), + bdcr: BDCR::new(), + 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, + }, + } + } +} + +/// Constrained RCC peripheral +pub struct Rcc { + /// Advanced High-Performance Bus 1 (AHB1) registers + pub ahb1: AHB1, + /// Advanced High-Performance Bus 2 (AHB2) registers + pub ahb2: AHB2, + /// Advanced High-Performance Bus 3 (AHB3) registers + pub ahb3: AHB3, + + /// Advanced Peripheral Bus 1 (APB1) registers + pub apb1: APB1, + /// Advanced Peripheral Bus 2 (APB2) registers + pub apb2: APB2, + /// RCC Backup Domain + pub bdcr: BDCR, + pub cfgr: CFGR, +} + +macro_rules! bus_struct { + ($($busX:ident => ($EN:ident, $en:ident, $LPEN:ident, $lpen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => { + $( + #[doc = $doc] + pub struct $busX { + _0: (), + } + + impl $busX { + pub(crate) fn new() -> Self { + Self { _0: () } + } + + pub(crate) fn enr(&self) -> &rcc::$EN { + // NOTE(unsafe) this proxy grants exclusive access to this register + unsafe { (*RCC::ptr()).$en() } + } + + pub(crate) fn lpenr(&self) -> &rcc::$LPEN { + // NOTE(unsafe) this proxy grants exclusive access to this register + unsafe { (*RCC::ptr()).$lpen() } + } + + pub(crate) fn rstr(&self) -> &rcc::$RST { + // NOTE(unsafe) this proxy grants exclusive access to this register + unsafe { (*RCC::ptr()).$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"), + AHB2 => (AHB2ENR, ahb2enr, AHB2LPENR, ahb2lpenr, AHB2RSTR, ahb2rstr, "Advanced High-performance Bus 2 (AHB2) registers"), + AHB3 => (AHB3ENR, ahb3enr, AHB3LPENR, ahb3lpenr, AHB3RSTR, ahb3rstr, "Advanced High-performance Bus 3 (AHB3) registers"), +} + +/// Backup Domain Control register (RCC_BDCR) +pub struct BDCR { + _0: (), +} + +impl BDCR { + pub(crate) fn new() -> Self { + Self { _0: () } + } +} + +/*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, PartialEq, Eq)] +enum VOSscale { + PwrScale1, + PwrScale2, + PwrScale3, +} + +impl Default for VOSscale { + fn default() -> Self { + VOSscale::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 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; + } + + // 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 as u64 * 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 as u64 * 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 as u32) + 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)] +pub struct Clocks { + hclk: Hertz, + pclk1: Hertz, + pclk2: Hertz, + sysclk: Hertz, + timclk1: Hertz, + timclk2: Hertz, + pll48clk_valid: bool, + hse: Option, + lse: Option, + 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 BusClock for AHB1 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.hclk + } +} + +impl BusClock for AHB2 { + fn clock(clocks: &Clocks) -> Hertz { + clocks.hclk + } +} + +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 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, + } + } +} + +/// Enable/disable peripheral +pub trait Enable: RccBus { + /// Enables peripheral + fn enable(bus: &mut Self::Bus); + + /// Disables peripheral + fn disable(bus: &mut Self::Bus); + + /// Check if peripheral enabled + fn is_enabled() -> bool; + + /// Check if peripheral disabled + fn is_disabled() -> bool { + !Self::is_enabled() + } + + /// # Safety + /// + /// Enables peripheral. Takes access to RCC internally + unsafe fn enable_unchecked(); + + /// # Safety + /// + /// Disables peripheral. Takes access to RCC internally + unsafe fn disable_unchecked(); +} + +/// Enable/disable peripheral in low power mode +pub trait LPEnable: RccBus { + /// Enables peripheral in low power mode + fn low_power_enable(bus: &mut Self::Bus); + + /// Disables peripheral in low power mode + fn low_power_disable(bus: &mut Self::Bus); + + /// Check if peripheral enabled in low power mode + fn is_low_power_enabled() -> bool; + + /// Check if peripheral disabled in low power mode + fn is_low_power_disabled() -> bool { + !Self::is_low_power_enabled() + } + + /// # Safety + /// + /// Enables peripheral in low power mode. Takes access to RCC internally + unsafe fn low_power_enable_unchecked(); + + /// # Safety + /// + /// Disables peripheral in low power mode. Takes access to RCC internally + unsafe fn low_power_disable_unchecked(); +} + +/// Reset peripheral +pub trait Reset: RccBus { + /// Resets peripheral + fn reset(bus: &mut Self::Bus); + + /// # Safety + /// + /// Resets peripheral. Takes access to RCC internally + unsafe fn reset_unchecked(); +} + +#[cfg(test)] +mod tests { + 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 f843f521b..6e15e280a 100644 --- a/src/rcc/mod.rs +++ b/src/rcc/mod.rs @@ -39,9 +39,21 @@ //! 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. +#[cfg(feature = "f2")] +mod f2; +#[cfg(feature = "f2")] +pub use f2::*; + +#[cfg(feature = "f4")] mod f4; +#[cfg(feature = "f4")] pub use f4::*; +#[cfg(feature = "f7")] +mod f7; +#[cfg(feature = "f7")] +pub use f7::*; + use fugit::HertzU32 as Hertz; /// Bus associated to peripheral diff --git a/src/serial.rs b/src/serial.rs index 77e4f6098..e6cce43b7 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -276,20 +276,36 @@ macro_rules! halUsart { }); } - fn peri_address() -> u32 { - unsafe { (*(<$USART>::ptr() as *const Self::RegisterBlock)).peri_address() } + fn tx_peri_address() -> u32 { + unsafe { (*(<$USART>::ptr() as *const Self::RegisterBlock)).tx_peri_address() } + } + + fn rx_peri_address() -> u32 { + unsafe { (*(<$USART>::ptr() as *const Self::RegisterBlock)).rx_peri_address() } } } }; } 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 } impl Rx { pub(crate) fn with_u16_data(self) -> Rx { diff --git a/src/serial/config.rs b/src/serial/config.rs index 49804142d..a7084d5c2 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 6c723cd64..da6806e8b 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -625,7 +625,7 @@ where { #[inline(always)] fn address(&self) -> u32 { - ::peri_address() + ::rx_peri_address() } type MemSize = u8; @@ -637,7 +637,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 16979c696..454a9672b 100644 --- a/src/serial/uart_impls.rs +++ b/src/serial/uart_impls.rs @@ -18,6 +18,7 @@ pub(crate) use crate::pac::uart4::RegisterBlock as RegisterBlockUart; pub(crate) use crate::pac::usart1::RegisterBlock as RegisterBlockUsart; #[cfg(feature = "uart4")] +#[cfg(not(feature = "f7"))] impl crate::Sealed for RegisterBlockUart {} impl crate::Sealed for RegisterBlockUsart {} @@ -30,7 +31,9 @@ pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + rcc::BusClock + C #[doc(hidden)] fn set_stopbits(&self, bits: config::StopBits); #[doc(hidden)] - fn peri_address() -> u32; + fn tx_peri_address() -> u32; + #[doc(hidden)] + fn rx_peri_address() -> u32; } pub trait RegisterBlockImpl: crate::Sealed { @@ -134,18 +137,23 @@ pub trait RegisterBlockImpl: crate::Sealed { fn unlisten_txe(&self) { self.listen_event(Some(Event::TxEmpty.into()), None) } - - // PeriAddress - fn peri_address(&self) -> u32; + // Receive PeriAddress + fn rx_peri_address(&self) -> u32; + // Transmit PeriAddress + fn tx_peri_address(&self) -> u32; } macro_rules! uartCommon { () => { 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() @@ -154,17 +162,30 @@ macro_rules! uartCommon { 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 }) @@ -172,11 +193,17 @@ macro_rules! uartCommon { 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) @@ -185,7 +212,10 @@ macro_rules! uartCommon { 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(()) @@ -195,23 +225,41 @@ macro_rules! uartCommon { } 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()) } fn clear_flags(&self, flags: BitFlags) { + #[cfg(feature = "uart_v2")] self.sr() .write(|w| unsafe { w.bits(0xffff & !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().set_bit()); } fn check_and_clear_error_flags(&self) -> Result<(), Error> { + #[cfg(feature = "uart_v2")] let sr = self.sr().read(); + #[cfg(feature = "uart_v2")] let _ = self.dr().read(); + // TODO: clear flags + #[cfg(feature = "uart_v3")] + let sr = self.isr().read(); + if sr.ore().bit_is_set() { Err(Error::Overrun) } else if sr.nf().bit_is_set() { @@ -248,9 +296,23 @@ macro_rules! uartCommon { }); } - fn peri_address(&self) -> u32 { + #[cfg(feature = "uart_v2")] + fn rx_peri_address(&self) -> u32 { + self.dr().as_ptr() as u32 + } + #[cfg(feature = "uart_v2")] + fn tx_peri_address(&self) -> u32 { self.dr().as_ptr() as u32 } + + #[cfg(feature = "uart_v3")] + fn rx_peri_address(&self) -> u32 { + self.rdr().as_ptr() as u32 + } + #[cfg(feature = "uart_v3")] + fn tx_peri_address(&self) -> u32 { + self.tdr().as_ptr() as u32 + } }; } @@ -341,9 +403,11 @@ where { // Reset other registers to disable advanced USART features register_block.cr2().reset(); - register_block.cr3().reset(); // IrDA configuration - see STM32F411xC/E (RM0383) sections: - // 19.3.12 "IrDA SIR ENDEC block" - // 19.6.7 "Guard time and prescaler register (USART_GTPR)" + register_block.cr3().reset(); + + // IrDA configuration - see STM32F411xC/E (RM0383) sections: + // 19.3.12 "IrDA SIR ENDEC block" + // 19.6.7 "Guard time and prescaler register (USART_GTPR)" if config.irda != IrdaMode::None && config.stopbits != StopBits::STOP1 { return Err(config::InvalidConfig); } @@ -370,12 +434,22 @@ where { // 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 register_block.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) }); @@ -401,6 +475,7 @@ where { } #[cfg(feature = "uart4")] +#[cfg(not(feature = "f7"))] impl RegisterBlockImpl for RegisterBlockUart { fn new, WORD>( uart: UART, @@ -480,12 +555,22 @@ where { // 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 register_block.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) }); @@ -726,7 +811,7 @@ impl Serial { unsafe impl PeriAddress for Rx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*UART::ptr()).peri_address() } + unsafe { (*UART::ptr()).rx_peri_address() } } type MemSize = u8; @@ -745,7 +830,7 @@ where { #[inline(always)] fn address(&self) -> u32 { - self.usart.peri_address() + self.usart.tx_peri_address() } type MemSize = u8; diff --git a/src/signature.rs b/src/signature.rs index cc27a74a5..2c320b194 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 5d0a90dd9..039f65109 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1,8 +1,10 @@ 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; @@ -125,18 +127,41 @@ pub const TransferModeNormal: bool = false; #[allow(non_upper_case_globals)] pub const TransferModeBidi: bool = true; +#[cfg(feature = "spi_v1")] pub trait FrameSize: Copy + Default { const DFF: bool; } +#[cfg(feature = "spi_v1")] impl FrameSize for u8 { const DFF: bool = false; } +#[cfg(feature = "spi_v1")] impl FrameSize for u16 { const DFF: bool = true; } +#[cfg(feature = "spi_v2")] +use crate::pac::spi1::cr2; +#[cfg(feature = "spi_v2")] +pub trait FrameSize: Copy + Default { + const FRXTH: cr2::FRXTH; + const DS: cr2::DS; +} + +#[cfg(feature = "spi_v2")] +impl FrameSize for u8 { + const FRXTH: cr2::FRXTH = cr2::FRXTH::Quarter; + const DS: cr2::DS = cr2::DS::EightBit; +} + +#[cfg(feature = "spi_v2")] +impl FrameSize for u16 { + const FRXTH: cr2::FRXTH = cr2::FRXTH::Half; + const DS: cr2::DS = cr2::DS::SixteenBit; +} + /// The bit format to send the data in #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BitFormat { @@ -220,19 +245,20 @@ macro_rules! spi { }; } +#[cfg(feature = "spi1")] spi! { pac::SPI1: Spi1, SpiSlave1 } +#[cfg(feature = "spi2")] +#[cfg(not(any(feature = "svd-f750", feature = "svd-f7x6")))] 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 { @@ -358,11 +384,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() @@ -374,11 +405,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() @@ -611,7 +647,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 @@ -629,6 +665,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); @@ -643,16 +684,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); @@ -667,7 +715,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 diff --git a/src/timer.rs b/src/timer.rs index 559ae7823..93dae545f 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -5,10 +5,12 @@ #![allow(non_upper_case_globals)] use core::convert::TryFrom; +use core::marker::PhantomData; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use enumflags2::BitFlags; +#[cfg(feature = "bb")] use crate::bb; use crate::pac; @@ -307,14 +309,18 @@ pub enum Ocm { } /// Wrapper type that indicates which register of the contained timer to use for DMA. -pub struct CCR(T); +pub struct CCR { + _per: PhantomData, +} pub type CCR1 = CCR; pub type CCR2 = CCR; pub type CCR3 = CCR; pub type CCR4 = CCR; /// Wrapper type that indicates which register of the contained timer to use for DMA. -pub struct DMAR(T); +pub struct DMAR { + _per: PhantomData, +} mod sealed { use super::{BitFlags, Channel, Event, Flag, IdleState, Ocm, Polarity}; @@ -523,7 +529,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)) + }}); } } @@ -531,7 +544,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))) + }}); } } @@ -539,7 +560,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))) + }}); } } } @@ -550,7 +579,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) { @@ -565,11 +601,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))) + }}); } } } @@ -580,7 +632,7 @@ macro_rules! hal { unsafe impl PeriAddress for CCR<$TIM, C> { #[inline(always)] fn address(&self) -> u32 { - self.0.ccr(C as usize).as_ptr() as u32 + unsafe { (*<$TIM>::ptr()).ccr(C as usize).as_ptr() as u32 } } type MemSize = $bits; @@ -602,7 +654,7 @@ macro_rules! with_dmar { unsafe impl PeriAddress for DMAR<$TIM> { #[inline(always)] fn address(&self) -> u32 { - self.0.dmar().as_ptr() as u32 + unsafe { (*<$TIM>::ptr()).dmar().as_ptr() as u32 } } type MemSize = $memsize; diff --git a/src/uart.rs b/src/uart.rs index 392877edb..0c68785e4 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -52,8 +52,12 @@ macro_rules! halUart { }); } - fn peri_address() -> u32 { - unsafe { (*Self::ptr()).peri_address() } + fn tx_peri_address() -> u32 { + unsafe { (*Self::ptr()).tx_peri_address() } + } + + fn rx_peri_address() -> u32 { + unsafe { (*Self::ptr()).rx_peri_address() } } } }; diff --git a/tools/check.py b/tools/check.py index d5bf34bb8..1fe381d5f 100755 --- a/tools/check.py +++ b/tools/check.py @@ -30,7 +30,7 @@ def main(): features = ["{},usb_fs,can,i2s,fsmc_lcd,rtic1,defmt".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']