diff --git a/.cargo/config.toml b/.cargo/config.toml
index 22153f86..ad81ad5c 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,3 +1,21 @@
+[target.thumbv6m-none-eabi]
+rustflags = [
+ "-C", "link-arg=-Tlink.x",
+ "-C", "link-arg=-Tdefmt.x",
+]
+
+[target.thumbv7m-none-eabi]
+rustflags = [
+ "-C", "link-arg=-Tlink.x",
+ "-C", "link-arg=-Tdefmt.x",
+]
+
+[target.thumbv7em-none-eabi]
+rustflags = [
+ "-C", "link-arg=-Tlink.x",
+ "-C", "link-arg=-Tdefmt.x",
+]
+
[target.thumbv7em-none-eabihf]
runner = 'probe-rs run --chip STM32F411CEUx'
rustflags = [
@@ -10,6 +28,12 @@ rustflags = [
#"-C", "link-arg=--nmagic",
]
+[target.thumbv8m.main-none-eabihf]
+rustflags = [
+ "-C", "link-arg=-Tlink.x",
+ "-C", "link-arg=-Tdefmt.x",
+]
+
[build]
target = "thumbv7em-none-eabihf"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 08d7222c..b5f3b9d9 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 2268655a..d9fc00f0 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/CHANGELOG.md b/CHANGELOG.md
index 26359037..df6be85b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- I2C 10-bit address support for I2c [#772] [#783]
+ - FMPI2c APB timings [#770]
- `i2c_scanner` example [#758]
- Enable `sdio` for stm32f446
- port LTDC implementation and example from stm32f7xx-hal [#731]
@@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Use `stm32f4-staging` until `stm32f4` is released [#706]
- use GPIO pac fields instead of raw write
- RTIC2 monotonics fix: CC1 instead of CC3
+ - Fefactor FMPI2c `embedded-hal` implementations
- Allow different lengths of buffers in hal_1 SpiBus impl [#566]
- Clean SPI write impls
- move `ptr()` to `Ptr` trait [#773]
@@ -34,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
[#725]: https://github.com/stm32-rs/stm32f4xx-hal/pull/725
[#731]: https://github.com/stm32-rs/stm32f4xx-hal/pull/731
[#758]: https://github.com/stm32-rs/stm32f4xx-hal/pull/758
+[#770]: https://github.com/stm32-rs/stm32f4xx-hal/pull/770
[#772]: https://github.com/stm32-rs/stm32f4xx-hal/pull/772
[#773]: https://github.com/stm32-rs/stm32f4xx-hal/pull/773
[#783]: https://github.com/stm32-rs/stm32f4xx-hal/pull/783
diff --git a/Cargo.toml b/Cargo.toml
index c3e35821..c1b68697 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -56,6 +56,9 @@ embedded-hal-async = { version = "1.0", optional = true }
rtic = { version = "2.0.1", features = ["thumbv7-backend"], optional = true }
atomic-polyfill = { version = "1.0.3", optional = true }
+stm32-fmc = { version = "0.3.0", optional = true }
+fdcan = { version = "0.1.2", features = ["fdcan_g0_g4_l5"], optional = true }
+
enumflags2 = "0.7.8"
embedded-storage = "0.3"
vcell = "0.1.3"
@@ -63,10 +66,75 @@ document-features = "0.2"
micromath = { version = "2.1.0", optional = true }
+[dependencies.stm32f0]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32f2]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32f3]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
[dependencies.stm32f4]
-package = "stm32f4-staging"
-version = "0.16.0"
+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.stm32g0]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32g4]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32h7]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32l0]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32l1]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32l4]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32l5]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32wb]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
+
+[dependencies.stm32wl]
+git = "https://github.com/stm32-rs/stm32-rs-nightlies"
+features = ["defmt", "atomics"]
+optional = true
[dependencies.time]
version = "0.3.14"
@@ -123,6 +191,201 @@ default-features = false
features = ["macros"]
[features]
+c0 = []
+f0 = ["dep:stm32f0"]
+f2 = ["dep:stm32f2", "bb", "dma", "i2c_v1", "spi_v1", "uart_v2"]
+f3 = ["dep:stm32f3", "bb", "uart_v3"]
+f4 = ["dep:stm32f4", "bb", "dma", "i2c_v1", "spi_v1", "uart_v2"]
+f7 = [
+ "dep:stm32f7",
+ "dep:micromath",
+ "dep:stm32-fmc",
+ "dma",
+ "i2c_v2",
+ "spi_v2",
+ "uart_v3",
+]
+g0 = ["dep:stm32g0"]
+g4 = ["dep:stm32g4", "bb", "dep:fdcan", "uart_v3"]
+h7 = ["dep:stm32h7"]
+l0 = ["dep:stm32l0"]
+l1 = ["dep:stm32l1"]
+l4 = ["dep:stm32l4", "uart_v3"]
+l4x = ["l4"]
+l4p = ["l4"]
+l5 = ["dep:stm32l5"] # thumbv8m.main-none-eabihf
+u5 = []
+wb = ["dep:stm32wb"]
+wl = ["dep:stm32wl"]
+
+mem-4 = []
+mem-6 = []
+mem-8 = []
+mem-b = []
+mem-c = []
+mem-d = []
+mem-e = []
+
+# common features: "i2c1", "rcc", "gpioa", "gpiob",
+
+# C0
+
+gpio-c0xx = [
+ "debug", "gpioc", "gpiof", "i2s", "i2s1", "ir", "spi1", "spi2", "tim1", "tim14", "tim15", "tim16", "tim17", "tim3", "usart1", "usart2",
+]
+gpio-c0xx_453 = [
+ "debug", "gpioc", "gpiod", "gpiof", "i2s", "i2s1", "ir", "spi1", "spi2", "tim1", "tim14", "tim15", "tim16", "tim17", "tim3", "usart1", "usart2",
+]
+
+# F0
+
+stm32f030x4 = ["svd-f0x0", "gpio-f031"]
+stm32f030x6 = ["svd-f0x0", "gpio-f031"]
+stm32f030x8 = ["svd-f0x0", "gpio-f051"]
+stm32f030xc = ["svd-f0x0", "gpio-f091"]
+stm32f031 = ["svd-f0x1", "gpio-f031"]
+stm32f038 = ["svd-f0x8", "gpio-f031"]
+stm32f042 = ["svd-f0x2", "gpio-f042"]
+stm32f048 = ["svd-f0x8", "gpio-f042"]
+stm32f051 = ["svd-f0x1", "gpio-f051"]
+stm32f058 = ["svd-f0x8", "gpio-f051"]
+stm32f070x6 = ["svd-f0x0", "gpio-f042"]
+stm32f070xb = ["svd-f0x0", "gpio-f052"]
+stm32f071 = ["svd-f0x1", "gpio-f052"]
+stm32f072 = ["svd-f0x2", "gpio-f052"]
+stm32f078 = ["svd-f0x8", "gpio-f052"]
+stm32f091 = ["svd-f0x1", "gpio-f091"]
+stm32f098 = ["svd-f0x8", "gpio-f091"]
+
+svd-f0x0 = ["f0", "stm32f0?/stm32f0x0"]
+svd-f0x1 = ["f0", "stm32f0?/stm32f0x1"]
+svd-f0x2 = ["f0", "stm32f0?/stm32f0x2"]
+svd-f0x8 = ["f0", "stm32f0?/stm32f0x8"]
+
+gpio-f031 = [
+ "hdmi", "i2c2", "i2s1", "ir", "rtc", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2",
+]
+gpio-f042 = [
+ "can", "crs", "gpiof", "i2c2", "i2s1", "ir", "spi1", "spi2", "sys", "tim1", "tim14", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2", "usb",
+]
+gpio-f051 = [
+ "comp1", "comp2", "gpioc", "gpiod", "i2c2", "i2s1", "ir", "rtc", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2",
+]
+gpio-f052 = [
+ "can", "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "gpiof", "i2c2", "i2s1", "i2s2", "ir", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2", "usart3", "usart4", "usb",
+]
+gpio-f091 = [
+ "can", "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "gpiof", "i2c2", "i2s1", "i2s2", "ir", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2", "usart3", "usart4", "usart5", "usart6", "usart7", "usart8", "usb",
+]
+# 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",
+]
+
+# F3
+
+# Any changes here should be mirrored in README.md, build.rs, src/lib.rs, and
+# .github/workflows/ci.yml.
+stm32f301x6 = ["svd-f301", "mem-6", "gpio-f302"]
+stm32f301x8 = ["svd-f301", "mem-8", "gpio-f302"]
+stm32f302x6 = ["svd-f302", "mem-6", "gpio-f302"]
+stm32f302x8 = ["svd-f302", "mem-8", "gpio-f302"]
+stm32f302xb = ["svd-f302", "mem-b", "gpio-f303"]
+stm32f302xc = ["svd-f302", "mem-c", "gpio-f303"]
+stm32f302xd = ["svd-f302", "mem-d", "gpio-f303e"]
+stm32f302xe = ["svd-f302", "mem-e", "gpio-f303e"]
+stm32f303x6 = ["svd-f303", "mem-6", "gpio-f333"]
+stm32f303x8 = ["svd-f303", "mem-8", "gpio-f333"]
+stm32f303xb = ["svd-f303", "mem-b", "gpio-f303"]
+stm32f303xc = ["svd-f303", "mem-c", "gpio-f303"]
+stm32f303xd = ["svd-f303", "mem-d", "gpio-f303e"]
+stm32f303xe = ["svd-f303", "mem-e", "gpio-f303e"]
+stm32f318x8 = ["svd-f301", "mem-8", "gpio-f302"]
+stm32f328x8 = ["svd-f303", "mem-8", "gpio-f333"]
+stm32f334x4 = ["svd-f3x4", "mem-4", "gpio-f333"]
+stm32f334x6 = ["svd-f3x4", "mem-6", "gpio-f333"]
+stm32f334x8 = ["svd-f3x4", "mem-8", "gpio-f333"]
+stm32f358xc = ["svd-f303", "mem-c", "gpio-f303"]
+stm32f373x8 = ["svd-f373", "mem-8", "gpio-f373"]
+stm32f373xb = ["svd-f373", "mem-b", "gpio-f373"]
+stm32f373xc = ["svd-f373", "mem-c", "gpio-f373"]
+stm32f378xc = ["svd-f373", "mem-c", "gpio-f373"]
+stm32f398xe = ["svd-f303", "mem-e", "gpio-f303e"]
+
+svd-f301 = ["f3", "stm32f3?/stm32f301"]
+svd-f302 = ["f3", "stm32f3?/stm32f302"]
+svd-f303 = ["f3", "stm32f3?/stm32f303"]
+svd-f373 = ["f3", "stm32f3?/stm32f373"]
+svd-f3x4 = ["f3", "stm32f3?/stm32f3x4"]
+
+gpio-f302 = [
+ "can1", "comp2", "comp4", "comp6", "gpioc", "gpiof", "i2c2", "i2c3", "i2s", "i2s2", "i2s3", "ir", "rtc", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tsc", "usart1", "usart2", "usart3",
+]
+gpio-f303 = [
+ "can1", "comp1", "comp2", "comp3", "comp4", "comp5", "comp6", "comp7", "gpioc", "gpiod", "gpioe", "gpiof", "i2c2", "i2s", "i2s2", "i2s3", "ir", "rtc", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3", "usb",
+]
+gpio-f303e = [
+ "can1", "comp1", "comp2", "comp3", "comp4", "comp5", "comp6", "comp7", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "i2c2", "i2c3", "i2s", "i2s2", "i2s3", "ir", "rtc", "spi1", "spi2", "spi3", "spi4", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim20", "tim3", "tim4", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3",
+]
+gpio-f333 = [
+ "can1", "comp2", "comp4", "comp6", "gpioc", "gpiod", "gpiof", "hrtim1", "ir", "opamp2", "spi1", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tsc", "usart1", "usart2", "usart3",
+]
+gpio-f373 = [
+ "can1", "comp1", "comp2", "gpioc", "gpiod", "gpioe", "gpiof", "i2c2", "i2s1", "i2s2", "i2s3", "ir", "rtc", "spi1", "spi2", "spi3", "sys", "tim12", "tim13", "tim14", "tim15", "tim16", "tim17", "tim19", "tim2", "tim3", "tim4", "tim5", "tsc", "usart1", "usart2", "usart3", "usb",
+]
+
+# F4
+
#! Use one of the supported STM32-serie related features:
#! `stm32f401`, `stm32f405`, `stm32f407`, `stm32f415`, `stm32f417`, `stm32f410`,
#! `stm32f411`, `stm32f412`, `stm32f413`, `stm32f423`, `stm32f427`, `stm32f429`,
@@ -130,89 +393,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",
@@ -221,37 +554,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",
@@ -260,40 +608,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",
@@ -302,43 +661,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",
@@ -347,41 +718,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",
@@ -390,65 +834,425 @@ 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",
+]
+
+# G0
+
+gpio-g03x = [
+ "gpioc", "gpiod", "gpiof", "i2c2", "i2s", "i2s1", "ir", "lptim1", "lptim2", "lpuart1", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "usart1", "usart2",
]
+gpio-g05x = [
+ "comp1", "comp2", "gpioc", "gpiod", "gpiof", "i2c2", "i2s", "i2s1", "ir", "lptim1", "lptim2", "lpuart1", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "usart1", "usart2",
+]
+gpio-g07x = [
+ "comp1", "comp2", "gpioc", "gpiod", "gpiof", "i2c2", "i2s", "i2s1", "ir", "lptim1", "lptim2", "lpuart1", "spi1", "spi2", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "ucpd1", "ucpd2", "usart1", "usart2", "usart3", "usart4",
+]
+gpio-g0bx = [
+ "comp1", "comp2", "comp3", "crs1", "fdcan1", "fdcan2", "gpioc", "gpiod", "gpioe", "gpiof", "i2c2", "i2c3", "i2s", "i2s1", "i2s2", "ir", "lptim1", "lptim2", "lpuart1", "lpuart2", "spi1", "spi2", "spi3", "sys", "tim1", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "ucpd1", "ucpd2", "usart1", "usart2", "usart3", "usart4", "usart5", "usart6", "usb",
+]
+
+# G4
+
+stm32g431 = ["svd-g431"]
+stm32g441 = ["svd-g441"]
+stm32g471 = ["svd-g471"]
+stm32g473 = ["svd-g473"]
+stm32g474 = ["svd-g474"]
+stm32g483 = ["svd-g483"]
+stm32g484 = ["svd-g484"]
+stm32g491 = ["svd-g491"]
+stm32g4a1 = ["svd-g4a1"]
+
+svd-g431 = ["g4", "stm32g4?/stm32g431", "gpio-g43x"]
+svd-g441 = ["g4", "stm32g4?/stm32g441", "gpio-g43x"]
+svd-g471 = ["g4", "stm32g4?/stm32g471", "gpio-g47x"]
+svd-g473 = ["g4", "stm32g4?/stm32g473", "gpio-g47x"]
+svd-g474 = ["g4", "stm32g4?/stm32g474", "gpio-g47x"]
+svd-g483 = ["g4", "stm32g4?/stm32g483", "gpio-g47x"]
+svd-g484 = ["g4", "stm32g4?/stm32g484", "gpio-g47x"]
+svd-g491 = ["g4", "stm32g4?/stm32g491", "gpio-g49x"]
+svd-g4a1 = ["g4", "stm32g4?/stm32g4a1", "gpio-g49x"]
+
+gpio-g43x = [
+ "comp1", "comp2", "comp3", "comp4", "crs", "fdcan1", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "i2c2", "i2c3", "i2s", "i2s2", "i2s3", "ir", "lptim1", "lpuart1", "rtc", "sai1", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim8", "uart4", "ucpd1", "usart1", "usart2", "usart3",
+]
+gpio-g47x = [
+ "comp1", "comp2", "comp3", "comp4", "comp5", "comp6", "comp7", "crs", "fdcan1", "fdcan2", "fdcan3", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "hrtim1", "i2c2", "i2c3", "i2c4", "i2s", "i2s2", "i2s3", "ir", "lptim1", "lpuart1", "quadspi", "rtc", "sai1", "spi1", "spi2", "spi3", "spi4", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim20", "tim3", "tim4", "tim5", "tim8", "uart4", "uart5", "ucpd1", "usart1", "usart2", "usart3",
+]
+gpio-g49x = [
+ "comp1", "comp2", "comp3", "comp4", "crs", "fdcan1", "fdcan2", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "i2c2", "i2c3", "i2s", "i2s2", "i2s3", "ir", "lptim1", "lpuart1", "quadspi", "rtc", "sai1", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim20", "tim3", "tim4", "tim8", "uart4", "uart5", "ucpd1", "usart1", "usart2", "usart3",
+]
+
+# H7
+
+gpio-h72 = [
+ "comp1", "comp2", "crs", "dcmi", "debug", "dfsdm1", "eth", "fdcan1", "fdcan2", "fdcan3", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioj", "gpiok", "i2c2", "i2c3", "i2c4", "i2c5", "i2s", "i2s1", "i2s2", "i2s3", "i2s6", "lptim1", "lptim2", "lptim3", "lptim4", "lptim5", "lpuart1", "ltdc", "mdios", "octospi", "pssi", "rtc", "sai1", "sai4", "sdmmc1", "sdmmc2", "spdifrx", "spi1", "spi2", "spi3", "spi4", "spi5", "spi6", "swpmi1", "tim1", "tim12", "tim13", "tim14", "tim15", "tim16", "tim17", "tim2", "tim23", "tim24", "tim3", "tim4", "tim5", "tim8", "uart4", "uart5", "uart7", "uart8", "uart9", "usart1", "usart10", "usart2", "usart3", "usart6", "otg-hs",
+]
+gpio-h747 = [
+ "comp1", "comp2", "crs", "dcmi", "debug", "dfsdm1", "dsihost", "eth", "fdcan1", "fdcan2", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "gpioj", "gpiok", "hrtim1", "i2c2", "i2c3", "i2c4", "i2s", "i2s1", "i2s2", "i2s3", "lptim1", "lptim2", "lptim3", "lptim4", "lptim5", "lpuart1", "ltdc", "mdios", "quadspi", "rtc", "sai1", "sai2", "sai3", "sai4", "sdmmc1", "sdmmc2", "spdifrx", "spi1", "spi2", "spi3", "spi4", "spi5", "spi6", "swpmi1", "sys", "tim1", "tim12", "tim13", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "uart4", "uart5", "uart7", "uart8", "usart1", "usart2", "usart3", "usart6", "otg-fs", "otg-hs",
+]
+gpio-h7a2 = [
+ "comp1", "comp2", "crs", "dcmi", "debug", "dfsdm1", "dfsdm2", "fdcan1", "fdcan2", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "gpioj", "gpiok", "i2c2", "i2c3", "i2c4", "i2s", "i2s1", "i2s2", "i2s3", "i2s6", "lptim1", "lptim2", "lptim3", "lpuart1", "ltdc", "mdios", "octospi", "pssi", "pwr", "rtc", "sai1", "sai2", "sdmmc1", "sdmmc2", "spdifrx", "spi1", "spi2", "spi3", "spi4", "spi5", "spi6", "swpmi1", "tim1", "tim12", "tim13", "tim14", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "uart4", "uart5", "uart7", "uart8", "uart9", "usart1", "usart10", "usart2", "usart3", "usart6", "otg-hs",
+]
+
+# L0
+
+gpio-l021 = [
+ "comp1", "comp2", "lptim1", "lpuart1", "rtc", "spi1", "sys", "tim2", "tim21", "usart2",
+]
+gpio-l031 = [
+ "comp1", "comp2", "gpioc", "lptim1", "lpuart1", "rtc", "spi1", "sys", "tim2", "tim21", "tim22", "usart2",
+]
+gpio-l051 = [
+ "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioh", "i2c2", "i2s2", "lcd", "lptim1", "lpuart1", "rtc", "spi1", "spi2", "sys", "tim2", "tim21", "tim22", "tsc", "usart1", "usart2", "usb",
+]
+gpio-l071 = [
+ "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "gpioh", "i2c2", "i2c3", "i2s2", "lcd", "lptim1", "lpuart1", "rtc", "spi1", "spi2", "sys", "tim2", "tim21", "tim22", "tim3", "tsc", "usart1", "usart2", "usart4", "usart5", "usb",
+]
+
+# L1
+
+gpio-l152x8 = [
+ "gpioc", "gpiod", "gpioe", "gpioh", "i2c2", "lcd", "rtc", "spi1", "spi2", "sys", "tim10", "tim11", "tim2", "tim3", "tim4", "tim9", "timx", "ts", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l152xc = [
+ "gpioc", "gpiod", "gpioe", "gpioh", "i2c2", "i2s2", "i2s3", "lcd", "rtc", "spi1", "spi2", "spi3", "sys", "tim10", "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", "timx", "ts", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l15xxa = [
+ "gpioc", "gpiod", "gpioe", "gpioh", "i2c2", "i2s2", "i2s3", "lcd", "rtc", "spi1", "spi2", "spi3", "sys", "tim10", "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", "timx", "ts", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l162xd = [
+ "fsmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "i2c2", "i2s2", "i2s3", "lcd", "rtc", "sdio", "spi1", "spi2", "spi3", "sys", "tim10", "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", "timx", "ts", "uart4", "uart5", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l162xe = [
+ "comp1", "comp2", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "i2c2", "i2s2", "i2s3", "lcd", "rtc", "spi1", "spi2", "spi3", "sys", "tim10", "tim11", "tim2", "tim3", "tim4", "tim5", "tim9", "timx", "ts", "uart4", "uart5", "usart1", "usart2", "usart3", "usb", "v_ref",
+]
+
+# L4
+
+stm32l431 = [ "svd-l4x1", "gpio-l43x" ]
+stm32l451 = [ "svd-l4x1", "gpio-l45x" ]
+stm32l471 = [ "svd-l4x1", "gpio-l47x" ]
+stm32l412 = [ "svd-l412", "gpio-l41x" ]
+stm32l422 = [ "svd-l412", "gpio-l41x" ]
+stm32l432 = [ "svd-l4x2", "gpio-l43x" ]
+stm32l442 = [ "svd-l4x2", "gpio-l43x" ]
+stm32l452 = [ "svd-l4x2", "gpio-l45x" ]
+stm32l462 = [ "svd-l4x2", "gpio-l45x" ]
+stm32l433 = [ "svd-l4x3", "gpio-l43x" ]
+stm32l443 = [ "svd-l4x3", "gpio-l43x" ]
+stm32l475 = [ "svd-l4x5", "gpio-l47x" ]
+stm32l476 = [ "svd-l4x6", "gpio-l47x" ]
+stm32l486 = [ "svd-l4x6", "gpio-l47x" ]
+stm32l496 = [ "svd-l4x6", "gpio-l49x" ]
+stm32l4a6 = [ "svd-l4x6", "gpio-l49x" ]
+
+svd-l4x1 = [ "l4x", "stm32l4?/stm32l4x1" ]
+svd-l412 = [ "l4x", "stm32l4?/stm32l412" ]
+svd-l4x2 = [ "l4x", "stm32l4?/stm32l4x2" ]
+svd-l4x3 = [ "l4x", "stm32l4?/stm32l4x3" ]
+svd-l4x5 = [ "l4x", "stm32l4?/stm32l4x5" ]
+svd-l4x6 = [ "l4x", "stm32l4?/stm32l4x6" ]
+
+gpio-l41x = [
+ "comp1", "crs", "gpioc", "gpiod", "i2c2", "i2c3", "ir", "lptim1", "lptim2", "lpuart1", "quadspi", "rtc", "spi1", "spi2", "sys", "tim1", "tim15", "tim16", "tim2", "tsc", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l43x = [
+ "can1", "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "i2c2", "i2c3", "ir", "lcd", "lptim1", "lptim2", "lpuart1", "quadspi", "rtc", "sai1", "sdmmc1", "spi1", "spi2", "spi3", "swpmi1", "sys", "tim1", "tim15", "tim16", "tim2", "tsc", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l45x = [
+ "can1", "comp1", "comp2", "crs", "dfsdm1", "gpioc", "gpiod", "gpioe", "i2c2", "i2c3", "i2c4", "ir", "lptim1", "lptim2", "lpuart1", "quadspi", "rtc", "sai1", "sdmmc1", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim2", "tim3", "tsc", "uart4", "usart1", "usart2", "usart3", "usb",
+]
+gpio-l47x = [
+ "can1", "comp1", "comp2", "dfsdm1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "i2c2", "i2c3", "ir", "lcd", "lptim1", "lptim2", "lpuart1", "quadspi", "rtc", "sai1", "sai2", "sdmmc1", "spi1", "spi2", "spi3", "swpmi1", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3", "otg-fs",
+]
+gpio-l49x = [
+ "can1", "can2", "comp1", "comp2", "crs", "dcmi", "dfsdm1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "i2c2", "i2c3", "i2c4", "ir", "lcd", "lptim1", "lptim2", "lpuart1", "quadspi", "rtc", "sai1", "sai2", "sdmmc1", "spi1", "spi2", "spi3", "swpmi1", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3", "otg-fs",
+]
+
+# L4+
+
+#stm32l4p5 = [ "svd-l4x5", "gpio-l4p" ]
+#stm32l4q5 = [ "svd-l4x5", "gpio-l4p" ]
+#stm32l4r5 = [ "svd-l4x5", "gpio-l4rx" ]
+#stm32l4s5 = [ "svd-l4x5", "gpio-l4rx" ]
+#stm32l4r7 = [ "svd-l4x7", "gpio-l4rx" ]
+#stm32l4s7 = [ "svd-l4x7", "gpio-l4rx" ]
+stm32l4r9 = [ "svd-l4r9", "gpio-l4rx" ] # PAC has an L4r9 specific variation
+stm32l4s9 = [ "svd-l4r9", "gpio-l4rx" ]
+
+#svd-l4x5 = [ "l4p", "stm32l4?/stm32l4x5" ]
+#svd-l4x7 = [ "l4p", "stm32l4?/stm32l4x7" ]
+svd-l4r9 = [ "l4p", "stm32l4?/stm32l4r9" ]
+
+gpio-l4p = [
+ "can1", "comp1", "comp2", "crs", "dcmi", "dfsdm1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "i2c2", "i2c3", "i2c4", "ir", "lptim1", "lptim2", "lpuart1", "ltdc", "octospi", "pssi", "rtc", "sai1", "sai2", "sdmmc1", "sdmmc2", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3", "otg-fs",
+]
+gpio-l4rx = [
+ "can1", "comp1", "comp2", "crs", "dcmi", "dfsdm1", "dsihost", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "i2c2", "i2c3", "i2c4", "ir", "lptim1", "lptim2", "lpuart1", "ltdc", "octospi", "rtc", "sai1", "sai2", "sdmmc1", "spi1", "spi2", "spi3", "sys", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "usart1", "usart2", "usart3", "otg-fs",
+]
+
+# L5
+
+gpio-l55x = [
+ "comp1", "comp2", "crs", "debug", "dfsdm1", "fdcan1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "i2c2", "i2c3", "i2c4", "ir", "lptim1", "lptim2", "lptim3", "lpuart1", "octospi", "rtc", "sai1", "sai2", "sdmmc1", "spi1", "spi2", "spi3", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "ucpd1", "usart1", "usart2", "usart3", "usb",
+]
+
+# U5
+
+gpio-u59x = [
+ "adf1", "comp1", "comp2", "crs", "dcmi", "debug", "dsihost", "fdcan1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "gpioj", "hspi1", "i2c2", "i2c3", "i2c4", "i2c5", "i2c6", "ir", "lptim1", "lptim2", "lptim3", "lptim4", "lpuart1", "ltdc", "mdf1", "octospi", "pssi", "pwr", "rtc", "sai1", "sai2", "sdmmc1", "sdmmc2", "spi1", "spi2", "spi3", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "ucpd1", "usart1", "usart2", "usart3", "usart6", "otg-hs",
+]
+gpio-u5x = [
+ "adf1", "comp1", "comp2", "crs", "dcmi", "debug", "fdcan1", "fmc", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog", "gpioh", "gpioi", "i2c2", "i2c3", "i2c4", "ir", "lptim1", "lptim2", "lptim3", "lptim4", "lpuart1", "mdf1", "octospi", "pssi", "pwr", "rtc", "sai1", "sai2", "sdmmc1", "sdmmc2", "spi1", "spi2", "spi3", "tim1", "tim15", "tim16", "tim17", "tim2", "tim3", "tim4", "tim5", "tim8", "tsc", "uart4", "uart5", "ucpd1", "usart1", "usart2", "usart3", "otg-fs",
+]
+
+# WB
+
+gpio-wb35x = [
+ "cm4", "comp1", "gpioc", "gpioe", "gpioh", "lptim1", "lptim2", "lpuart1", "rf", "rtc", "spi1", "sys", "tim1", "tim2", "tsc", "usart1",
+]
+gpio-wb3x = [
+ "cm4", "comp1", "comp2", "crs", "gpioc", "gpioe", "gpioh", "i2c3", "ir", "lptim1", "lptim2", "lpuart1", "quadspi", "sai1", "spi1", "sys", "tim1", "tim16", "tim17", "tim2", "usart1", "usb",
+]
+gpio-wb55x = [
+ "cm4", "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "gpioh", "i2c3", "ir", "lcd", "lptim1", "lptim2", "lpuart1", "quadspi", "rf", "rtc", "sai1", "spi1", "spi2", "sys", "tim1", "tim16", "tim17", "tim2", "tsc", "usart1", "usb",
+]
+gpio-wb5mx = [
+ "cm4", "comp1", "comp2", "crs", "gpioc", "gpiod", "gpioe", "gpioh", "i2c3", "ir", "lcd", "lptim1", "lptim2", "lpuart1", "quadspi", "rf", "rtc", "sai1", "spi1", "spi2", "sys", "tim1", "tim16", "tim17", "tim2", "tsc", "usart1", "usb",
+]
+
+# WL
+
+gpio-wl = [
+ "cm4", "comp1", "comp2", "debug", "gpioc", "gpioh", "i2c2", "i2c3", "i2s", "i2s2", "ir", "lptim1", "lptim2", "lptim3", "lpuart1", "rf", "rtc", "spi1", "spi2", "sys", "tim1", "tim16", "tim17", "tim2", "usart1", "usart2",
+]
+
## 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"]
@@ -487,48 +1291,114 @@ 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 = []
+i2c_v1 = []
+i2c_v2 = []
+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 = []
+fmpi2c1 = ["dep:micromath"]
+gpioc = []
gpiod = []
gpioe = []
gpiof = []
gpiog = []
+gpioh = []
gpioi = []
gpioj = []
gpiok = []
+hdmi = []
+hrtim1 = []
+hspi1 = []
+i2c2 = []
i2c3 = []
+i2c4 = []
+i2c5 = []
+i2c6 = []
+i2s1 = []
+i2s2 = []
+i2s2ext = []
+i2s3 = []
+i2s3ext = []
+i2s4 = []
+i2s5 = []
+i2s6 = []
+ir = []
+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 = []
@@ -543,13 +1413,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
@@ -564,7 +1460,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"
@@ -643,7 +1539,7 @@ required-features = ["rng"] # stm32f407
[[example]]
name = "rtc"
-required-features = []
+required-features = ["f4"]
[[example]]
name = "rtc_alarm"
@@ -651,7 +1547,7 @@ required-features = ["stm32f411"]
[[example]]
name = "rtic-adc-dma"
-required-features = ["rtic1"] # stm32f401
+required-features = ["rtic1", "f4"] # stm32f401
[[example]]
name = "rtic-button"
@@ -721,6 +1617,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,8 +1655,9 @@ required-features = ["otg-fs", "usb_fs"] # stm32f407
[[example]]
name = "usb-serial-poll"
-required-features = ["otg-fs", "usb_fs"] # stm32f401
+required-features = ["otg-fs", "usb_fs", "f4"] # stm32f401
[[example]]
name = "ws2812-spi"
required-features = []
+
diff --git a/README.md b/README.md
index 3a031deb..d3cd15c8 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ stm32f4xx-hal
[](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 8e25570e..c27e5348 100644
--- a/build.rs
+++ b/build.rs
@@ -23,7 +23,12 @@ 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_STM32F3")
+ || x.starts_with("CARGO_FEATURE_STM32F4")
+ || x.starts_with("CARGO_FEATURE_STM32F7")
+ || x.starts_with("CARGO_FEATURE_STM32L4")
+ })
.get_one()
{
Ok(x) => x,
diff --git a/examples/display-touch.rs b/examples/display-touch.rs
index 1976403e..11857897 100644
--- a/examples/display-touch.rs
+++ b/examples/display-touch.rs
@@ -1,4 +1,4 @@
-//!
+//!
//! Demonstrates use of I2C bus to configure and use FT6x06 touchscreen controller
//!
//! Hardware Required: STM32F412G-DISCO board or STM32F413H-DISCO board
diff --git a/examples/spi_16.rs b/examples/spi_16.rs
new file mode 100644
index 00000000..fcd69979
--- /dev/null
+++ b/examples/spi_16.rs
@@ -0,0 +1,60 @@
+#![no_main]
+#![no_std]
+
+use panic_semihosting as _;
+
+use stm32f4xx_hal as hal;
+
+use hal::{
+ pac,
+ prelude::*,
+ spi::{NoMiso, Spi},
+};
+
+use cortex_m_rt::entry;
+
+#[entry]
+fn main() -> ! {
+ let p = pac::Peripherals::take().unwrap();
+
+ let rcc = p.RCC.constrain();
+ let clocks = rcc.cfgr.freeze();
+
+ let gpioa = p.GPIOA.split();
+ let gpioc = p.GPIOC.split();
+ let gpiod = p.GPIOD.split();
+
+ // Configure pin for button. This happens to be the pin for the USER button
+ // on the NUCLEO-F746ZG board.
+ let button = gpioc.pc13.into_floating_input();
+
+ // Prepare pins for SPI
+ let mut ncs = gpiod.pd14.into_push_pull_output();
+ let sck = gpioa.pa5;
+ let mosi = gpioa.pa7;
+
+ // Set NCS pin to high (disabled) initially
+ ncs.set_high();
+
+ // Initialize SPI
+ let mut spi = Spi::new(
+ p.SPI1,
+ (sck, NoMiso::new(), mosi),
+ embedded_hal::spi::MODE_0,
+ 250.kHz(),
+ &clocks,
+ )
+ .frame_size_16bit();
+
+ // Use a button to control output via the Maxim Integrated MAX5214 DAC.
+ loop {
+ let data = if button.is_high() { 0xffff } else { 0x0000 };
+
+ let word: u16 = (0b01 << 14) | // write-through mode
+ (data & 0x3fff); // data bits
+
+ ncs.set_low();
+ spi.write(&[word]).unwrap();
+ ncs.set_high();
+ }
+}
diff --git a/src/adc.rs b/src/adc.rs
index 9c0d23c4..2b75439f 100644
--- a/src/adc.rs
+++ b/src/adc.rs
@@ -140,8 +140,13 @@ use crate::{
use core::fmt;
pub mod config;
+
+#[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 00000000..8b137891
--- /dev/null
+++ b/src/adc/f2.rs
@@ -0,0 +1 @@
+
diff --git a/src/adc/f4.rs b/src/adc/f4.rs
index f1d1cb1b..87e56d14 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 00000000..53db7ca6
--- /dev/null
+++ b/src/adc/f7.rs
@@ -0,0 +1,63 @@
+use super::*;
+
+// See "Datasheet - production data"
+// Pinouts and pin description (page 66..)
+adc_pins!(
+ gpio::PA0 => (ADC1, 0),
+ gpio::PA1 => (ADC1, 1),
+ gpio::PA2 => (ADC1, 2),
+ gpio::PA3 => (ADC1, 3),
+ gpio::PA4 => (ADC1, 4),
+ gpio::PA5 => (ADC1, 5),
+ gpio::PA6 => (ADC1, 6),
+ gpio::PA7 => (ADC1, 7),
+ gpio::PB0 => (ADC1, 8),
+ gpio::PB1 => (ADC1, 9),
+ gpio::PC0 => (ADC1, 10),
+ gpio::PC1 => (ADC1, 11),
+ gpio::PC2 => (ADC1, 12),
+ gpio::PC3 => (ADC1, 13),
+ gpio::PC4 => (ADC1, 14),
+ gpio::PC5 => (ADC1, 15),
+ Temperature => (ADC1, 18),
+ Vbat => (ADC1, 18),
+ Vref => (ADC1, 17),
+);
+
+adc_pins!(
+ gpio::PA0 => (ADC2, 0),
+ gpio::PA1 => (ADC2, 1),
+ gpio::PA2 => (ADC2, 2),
+ gpio::PA3 => (ADC2, 3),
+ gpio::PA4 => (ADC2, 4),
+ gpio::PA5 => (ADC2, 5),
+ gpio::PA6 => (ADC2, 6),
+ gpio::PA7 => (ADC2, 7),
+ gpio::PB0 => (ADC2, 8),
+ gpio::PB1 => (ADC2, 9),
+ gpio::PC0 => (ADC2, 10),
+ gpio::PC1 => (ADC2, 11),
+ gpio::PC2 => (ADC2, 12),
+ gpio::PC3 => (ADC2, 13),
+ gpio::PC4 => (ADC2, 14),
+ gpio::PC5 => (ADC2, 15),
+);
+
+adc_pins!(
+ gpio::PA0 => (ADC3, 0),
+ gpio::PA1 => (ADC3, 1),
+ gpio::PA2 => (ADC3, 2),
+ gpio::PA3 => (ADC3, 3),
+ gpio::PF6 => (ADC3, 4),
+ gpio::PF7 => (ADC3, 5),
+ gpio::PF8 => (ADC3, 6),
+ gpio::PF9 => (ADC3, 7),
+ gpio::PF10 => (ADC3, 8),
+ gpio::PF3 => (ADC3, 9),
+ gpio::PC0 => (ADC3, 10),
+ gpio::PC1 => (ADC3, 11),
+ gpio::PC2 => (ADC3, 12),
+ gpio::PC3 => (ADC3, 13),
+ gpio::PF4 => (ADC3, 14),
+ gpio::PF5 => (ADC3, 15),
+);
diff --git a/src/adc/l4.rs b/src/adc/l4.rs
new file mode 100644
index 00000000..e29c0766
--- /dev/null
+++ b/src/adc/l4.rs
@@ -0,0 +1,990 @@
+//! # Analog to Digital converter
+
+use core::{
+ convert::Infallible,
+ marker::PhantomData,
+ //ops::DerefMut,
+ //sync::atomic::{self, Ordering},
+};
+#[cfg(feature = "dma")]
+use stable_deref_trait::StableDeref;
+
+#[cfg(feature = "dma")]
+use crate::{
+ dma::{dma1, Event as DMAEvent, RxDma, Transfer, TransferPayload, W},
+ dmamux::{DmaInput, DmaMux},
+};
+use crate::{
+ gpio::{self, Analog},
+ hal::{
+ adc::{Channel as EmbeddedHalChannel, OneShot},
+ blocking::delay::DelayUs,
+ },
+ pac::{self, ADC1},
+ rcc::{Enable, Reset, AHB2, CCIPR},
+ signature::{VrefCal, VtempCalHigh, VtempCalLow, VDDA_CALIB_MV},
+};
+
+/// Internal voltage reference channel, used for calibration.
+pub struct Vref {
+ _0: (),
+}
+
+/// Internal battery monitoring channel.
+pub struct Vbat {
+ _0: (),
+}
+
+/// Internal temperature sensor channel.
+pub struct Temperature {
+ _0: (),
+}
+
+/// Wrapper for safely sharing [`ADC_COMMON`](pac::ADC_COMMON) between `Adc`s.
+#[derive(Clone, Copy)]
+pub struct AdcCommon {
+ _0: PhantomData,
+ #[allow(unused)]
+ csr: AdcCommonCsr,
+ ccr: AdcCommonCcr,
+ #[allow(unused)]
+ cdr: AdcCommonCdr,
+}
+
+#[derive(Clone, Copy)]
+struct AdcCommonCsr {
+ _0: PhantomData>,
+}
+
+#[derive(Clone, Copy)]
+struct AdcCommonCcr {
+ _0: PhantomData>,
+}
+
+#[derive(Clone, Copy)]
+struct AdcCommonCdr {
+ _0: PhantomData>,
+}
+
+impl AdcCommonCcr {
+ #[inline]
+ fn read(&self) -> pac::adc_common::ccr::R {
+ let adc_common = unsafe { &*pac::ADC_COMMON::ptr() };
+ adc_common.ccr.read()
+ }
+
+ #[inline]
+ fn modify(&mut self, f: F)
+ where
+ for<'w> F: FnOnce(
+ &pac::adc_common::ccr::R,
+ &'w mut pac::adc_common::ccr::W,
+ ) -> &'w mut stm32l4::W,
+ {
+ cortex_m::interrupt::free(|_| {
+ let adc_common = unsafe { &*pac::ADC_COMMON::ptr() };
+ adc_common.ccr.modify(|r, w| f(r, w))
+ })
+ }
+}
+
+impl AdcCommon {
+ /// Enable and reset [`ADC_COMMON`](pac::ADC_COMMON) peripheral.
+ pub fn new(adc_common: pac::ADC_COMMON, ahb: &mut AHB2) -> Self {
+ ::enable(ahb);
+ ::reset(ahb);
+
+ drop(adc_common);
+
+ Self {
+ _0: PhantomData,
+ csr: AdcCommonCsr { _0: PhantomData },
+ ccr: AdcCommonCcr { _0: PhantomData },
+ cdr: AdcCommonCdr { _0: PhantomData },
+ }
+ }
+}
+
+/// Analog to Digital converter interface
+pub struct Adc {
+ adc: ADC,
+ adc_common: AdcCommon,
+ resolution: Resolution,
+ sample_time: SampleTime,
+ calibrated_vdda: u32,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum DmaMode {
+ Disabled = 0,
+ Oneshot = 1,
+ // FIXME: Figure out how to get circular DMA to function properly (requires circbuffer?)
+ // Circular = 2,
+}
+
+#[derive(PartialEq, PartialOrd, Clone, Copy)]
+pub enum Sequence {
+ One = 0,
+ Two = 1,
+ Three = 2,
+ Four = 3,
+ Five = 4,
+ Six = 5,
+ Seven = 6,
+ Eight = 7,
+ Nine = 8,
+ Ten = 9,
+ Eleven = 10,
+ Twelve = 11,
+ Thirteen = 12,
+ Fourteen = 13,
+ Fifteen = 14,
+ Sixteen = 15,
+}
+
+impl From for Sequence {
+ fn from(bits: u8) -> Self {
+ match bits {
+ 0 => Sequence::One,
+ 1 => Sequence::Two,
+ 2 => Sequence::Three,
+ 3 => Sequence::Four,
+ 4 => Sequence::Five,
+ 5 => Sequence::Six,
+ 6 => Sequence::Seven,
+ 7 => Sequence::Eight,
+ 8 => Sequence::Nine,
+ 9 => Sequence::Ten,
+ 10 => Sequence::Eleven,
+ 11 => Sequence::Twelve,
+ 12 => Sequence::Thirteen,
+ 13 => Sequence::Fourteen,
+ 14 => Sequence::Fifteen,
+ 15 => Sequence::Sixteen,
+ _ => unimplemented!(),
+ }
+ }
+}
+
+impl Into for Sequence {
+ fn into(self) -> u8 {
+ match self {
+ Sequence::One => 0,
+ Sequence::Two => 1,
+ Sequence::Three => 2,
+ Sequence::Four => 3,
+ Sequence::Five => 4,
+ Sequence::Six => 5,
+ Sequence::Seven => 6,
+ Sequence::Eight => 7,
+ Sequence::Nine => 8,
+ Sequence::Ten => 9,
+ Sequence::Eleven => 10,
+ Sequence::Twelve => 11,
+ Sequence::Thirteen => 12,
+ Sequence::Fourteen => 13,
+ Sequence::Fifteen => 14,
+ Sequence::Sixteen => 15,
+ }
+ }
+}
+
+#[derive(PartialEq, PartialOrd, Clone, Copy)]
+pub enum Event {
+ EndOfRegularSequence,
+ EndOfRegularConversion,
+}
+
+impl Adc {
+ /// Set the ADC resolution
+ pub fn set_resolution(&mut self, resolution: Resolution) {
+ self.resolution = resolution;
+ }
+
+ /// Set the sample time
+ pub fn set_sample_time(&mut self, sample_time: SampleTime) {
+ self.sample_time = sample_time;
+ }
+
+ /// Get the max value for the current resolution
+ pub fn get_max_value(&self) -> u16 {
+ match self.resolution {
+ Resolution::Bits12 => 4095,
+ Resolution::Bits10 => 1023,
+ Resolution::Bits8 => 255,
+ Resolution::Bits6 => 63,
+ }
+ }
+
+ /// Release the ADC peripheral
+ ///
+ /// Drops `Adc` and returns the `(pac::ADC, pad::ADC_COMMON)` that it was wrapping,
+ /// giving the user full access to the peripheral.
+ pub fn release(self) -> ADC {
+ self.adc
+ }
+
+ /// Convert a measurement to millivolts
+ pub fn to_millivolts(&self, sample: u16) -> u16 {
+ ((u32::from(sample) * self.calibrated_vdda) / self.resolution.to_max_count()) as u16
+ }
+
+ /// Convert a raw sample from the `Temperature` to deg C
+ pub fn to_degrees_centigrade(&self, sample: u16) -> f32 {
+ let sample = (u32::from(sample) * self.calibrated_vdda) / VDDA_CALIB_MV;
+ (VtempCalHigh::TEMP_DEGREES - VtempCalLow::TEMP_DEGREES) as f32
+ // as signed because RM0351 doesn't specify against this being an
+ // inverse relation (which would result in a negative differential)
+ / (VtempCalHigh::get().read() as i32 - VtempCalLow::get().read() as i32) as f32
+ // this can definitely be negative so must be done as a signed value
+ * (sample as i32 - VtempCalLow::get().read() as i32) as f32
+ // while it would make sense for this to be `VtempCalLow::TEMP_DEGREES` (which is 30*C),
+ // the RM specifically uses 30*C so this will too
+ + 30.0
+ }
+}
+
+impl Adc {
+ // DMA channels:
+ // ADC1: DMA2_3 with C2S 0000
+ // ADC2: DMA2_4 with C2S 0000
+ // ADC1: DMA1_1 with C1S 0000 (implemented)
+ // ADC2: DMA1_2 with C1S 0000
+}
+
+impl OneShot for Adc
+where
+ C: Channel,
+{
+ type Error = Infallible;
+
+ fn read(&mut self, channel: &mut C) -> nb::Result {
+ self.configure_sequence(channel, Sequence::One, self.sample_time);
+
+ self.start_conversion();
+ while !self.has_completed_sequence() {}
+
+ // Read ADC value first time and discard it, as per errata sheet.
+ // The errata state that if we do conversions slower than 1 kHz, the
+ // first read ADC value can be corrupted, so we discard it and measure again.
+ let _ = self.current_sample();
+
+ self.start_conversion();
+ while !self.has_completed_sequence() {}
+
+ // Read ADC value.
+ let val = self.current_sample();
+
+ // Disable ADC.
+ self.disable();
+
+ Ok(val)
+ }
+}
+
+#[cfg(feature = "dma")]
+impl TransferPayload for RxDma, dma1::C1> {
+ fn start(&mut self) {
+ self.channel.start();
+ }
+
+ fn stop(&mut self) {
+ self.channel.stop();
+ }
+}
+
+#[cfg(feature = "dma")]
+impl RxDma, dma1::C1> {
+ pub fn split(mut self) -> (Adc, dma1::C1) {
+ self.stop();
+ (self.payload, self.channel)
+ }
+}
+
+#[cfg(feature = "dma")]
+impl Transfer, dma1::C1>>
+where
+ BUFFER: Sized + StableDeref + DerefMut + 'static,
+{
+ pub fn from_adc_dma(
+ dma: RxDma, dma1::C1>,
+ buffer: BUFFER,
+ dma_mode: DmaMode,
+ transfer_complete_interrupt: bool,
+ ) -> Self {
+ let (adc, channel) = dma.split();
+ Transfer::from_adc(adc, channel, buffer, dma_mode, transfer_complete_interrupt)
+ }
+
+ /// Initiate a new DMA transfer from an ADC.
+ ///
+ /// `dma_mode` indicates the desired mode for DMA.
+ ///
+ /// If `transfer_complete_interrupt` is true, the transfer
+ /// complete interrupt (= `DMA1_CH1`) will be enabled
+ pub fn from_adc(
+ mut adc: Adc,
+ mut channel: dma1::C1,
+ buffer: BUFFER,
+ dma_mode: DmaMode,
+ transfer_complete_interrupt: bool,
+ ) -> Self {
+ assert!(dma_mode != DmaMode::Disabled);
+
+ let (enable, circular) = match dma_mode {
+ DmaMode::Disabled => (false, false),
+ DmaMode::Oneshot => (true, false),
+ };
+
+ adc.adc
+ .cfgr
+ .modify(|_, w| w.dmaen().bit(enable).dmacfg().bit(circular));
+
+ channel.set_peripheral_address(&adc.adc.dr as *const _ as u32, false);
+
+ // SAFETY: since the length of BUFFER is known to be `N`, we are allowed
+ // to perform N transfers into said buffer
+ channel.set_memory_address(buffer.as_ptr() as u32, true);
+ channel.set_transfer_length(N as u16);
+
+ channel.set_request_line(DmaInput::Adc1).unwrap();
+
+ channel.ccr().modify(|_, w| unsafe {
+ w.mem2mem()
+ .clear_bit()
+ // 00: Low, 01: Medium, 10: High, 11: Very high
+ .pl()
+ .bits(0b01)
+ // 00: 8-bits, 01: 16-bits, 10: 32-bits, 11: Reserved
+ .msize()
+ .bits(0b01)
+ // 00: 8-bits, 01: 16-bits, 10: 32-bits, 11: Reserved
+ .psize()
+ .bits(0b01)
+ // Peripheral -> Mem
+ .dir()
+ .clear_bit()
+ .circ()
+ .bit(circular)
+ });
+
+ if transfer_complete_interrupt {
+ channel.listen(DMAEvent::TransferComplete);
+ }
+
+ atomic::compiler_fence(Ordering::Release);
+
+ channel.start();
+ adc.start_conversion();
+
+ Transfer::w(
+ buffer,
+ RxDma {
+ channel,
+ payload: adc,
+ },
+ )
+ }
+}
+
+/// ADC resolution setting
+///
+/// The default setting is 12 bits.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub enum Resolution {
+ /// 12-bit resolution
+ Bits12 = 0b00,
+
+ /// 10-bit resolution
+ Bits10 = 0b01,
+
+ /// 8-bit resolution
+ Bits8 = 0b10,
+
+ /// 6-bit resolution
+ Bits6 = 0b11,
+}
+
+impl Default for Resolution {
+ fn default() -> Self {
+ Self::Bits12
+ }
+}
+
+impl Resolution {
+ fn to_max_count(&self) -> u32 {
+ match self {
+ Resolution::Bits12 => (1 << 12) - 1,
+ Resolution::Bits10 => (1 << 10) - 1,
+ Resolution::Bits8 => (1 << 8) - 1,
+ Resolution::Bits6 => (1 << 6) - 1,
+ }
+ }
+}
+
+/// ADC sample time
+///
+/// The default setting is 2.5 ADC clock cycles.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[repr(u8)]
+pub enum SampleTime {
+ /// 2.5 ADC clock cycles
+ Cycles2_5 = 0b000,
+
+ /// 6.5 ADC clock cycles
+ Cycles6_5 = 0b001,
+
+ /// 12.5 ADC clock cycles
+ Cycles12_5 = 0b010,
+
+ /// 24.5 ADC clock cycles
+ Cycles24_5 = 0b011,
+
+ /// 47.5 ADC clock cycles
+ Cycles47_5 = 0b100,
+
+ /// 92.5 ADC clock cycles
+ Cycles92_5 = 0b101,
+
+ /// 247.5 ADC clock cycles
+ Cycles247_5 = 0b110,
+
+ /// 640.5 ADC clock cycles
+ Cycles640_5 = 0b111,
+}
+
+impl Default for SampleTime {
+ fn default() -> Self {
+ Self::Cycles2_5
+ }
+}
+
+/// Implemented for all types that represent ADC channels
+pub trait Channel: EmbeddedHalChannel {
+ fn set_sample_time(&mut self, adc: &mut T, sample_time: SampleTime);
+}
+
+macro_rules! impl_embedded_hal_channel {
+ ($pin:ty => ($adc_type:ident, $chan:expr)) => {
+ impl EmbeddedHalChannel for $pin {
+ type ID = u8;
+
+ fn channel() -> Self::ID {
+ $chan
+ }
+ }
+ };
+}
+
+macro_rules! impl_channel {
+ ($pin:ty => ($adc_type:ident, $smpr:ident, $smp:ident, $($min_sample_time:expr)?)) => {
+ impl Channel for $pin {
+ #[inline]
+ fn set_sample_time(&mut self, adc: &mut pac::$adc_type, sample_time: SampleTime) {
+ $(
+ // Ensure minimum sample time.
+ let sample_time = if sample_time < $min_sample_time {
+ $min_sample_time
+ } else {
+ sample_time
+ };
+ )*
+
+ adc.$smpr.modify(|_, w| {
+ // This is sound, as all `SampleTime` values are valid for this field.
+ unsafe { w.$smp().bits(sample_time as u8) }
+ })
+ }
+ }
+ };
+}
+
+macro_rules! adc_pins {
+ ($($pin:ty => ($adc_type:ident, $chan:expr, $smpr:ident, $smp:ident $(, $min_sample_time:expr)?),)+ $(,)?) => {
+ $(
+ impl_embedded_hal_channel!($pin => ($adc_type, $chan));
+ impl_channel!($pin =>($adc_type, $smpr, $smp, $($min_sample_time)*));
+ )*
+ };
+}
+
+macro_rules! adc {
+ (@vref: $adc_type:ident => ($common_type:ident)) => {
+ /// Calculates the system VDDA by sampling the internal VREF channel and comparing
+ /// the result with the value stored at the factory. If the chip's VDDA is not stable, run
+ /// this before each ADC conversion.
+ ///
+ /// Returns the calibrated VDDA voltage in millivolts.
+ #[inline]
+ pub fn calibrate(&mut self, delay: &mut impl DelayUs) -> u16 {
+ let vref = self.enable_vref(delay);
+
+ let vref_cal = VrefCal::get().read();
+
+ // This can't actually fail, it's just in a result to satisfy hal trait
+ let vref_samp = self.read(&mut Vref { _0: () }).unwrap();
+
+ // Safety: DIV by 0 is possible if vref_samp is 0
+ self.calibrated_vdda = (VDDA_CALIB_MV * u32::from(vref_cal)) / u32::from(vref_samp);
+
+ // Disable VREF again if it was disabled before.
+ if let Some(vref) = vref {
+ self.disable_vref(vref);
+ }
+
+ self.calibrated_vdda as u16
+ }
+
+ /// Check if the internal voltage reference channel is enabled.
+ #[inline]
+ pub fn is_vref_enabled(&self) -> bool {
+ self.adc_common.ccr.read().vrefen().bit_is_set()
+ }
+
+ /// Enable the internal voltage reference channel.
+ ///
+ /// Returns `Some(Vref)` if the channel was enabled or `None` if it was already enabled before.
+ #[inline]
+ pub fn enable_vref(&mut self, delay: &mut impl DelayUs) -> Option {
+ if self.is_vref_enabled() {
+ return None
+ }
+
+ self.adc_common.ccr.modify(|_, w| w.vrefen().set_bit());
+
+ // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
+ // to stabilize the internal voltage reference, we wait a little more.
+ delay.delay_us(15);
+
+ Some(Vref { _0: () })
+ }
+
+ /// Disable the internal voltage reference channel.
+ #[inline]
+ pub fn disable_vref(&mut self, vref: Vref) {
+ drop(vref);
+
+ self.adc_common.ccr.modify(|_, w| w.vrefen().clear_bit());
+ }
+ };
+
+ // Provide a stub implementation for ADCs that do not have a means of sampling VREF.
+ (@no_vref: $adc_type:ident => ($common_type:ident)) => {
+ #[inline]
+ fn calibrate(&mut self, _delay: &mut impl DelayUs) {}
+ };
+
+ (@vbat: $adc_type:ident => ($common_type:ident)) => {
+ /// Check if the battery voltage monitoring channel is enabled.
+ #[inline]
+ pub fn is_vbat_enabled(&self) -> bool {
+ self.adc_common.ccr.read().ch18sel().bit_is_set()
+ }
+
+ /// Enable the battery voltage monitoring channel.
+ ///
+ ///
+ /// Returns `Some(Vbat)` if the channel was enabled or `None` if it was already enabled before.
+ #[inline]
+ pub fn enable_vbat(&mut self) -> Option {
+ if self.is_vbat_enabled() {
+ return None
+ }
+
+ self.adc_common.ccr.modify(|_, w| w.ch18sel().set_bit());
+ Some(Vbat { _0: () })
+ }
+
+ /// Disable the battery voltage monitoring channel.
+ #[inline]
+ pub fn disable_vbat(&mut self, vbat: Vbat) {
+ drop(vbat);
+
+ self.adc_common.ccr.modify(|_, w| w.ch18sel().clear_bit());
+ }
+ };
+
+ (@no_vbat: $adc_type:ident => ($common_type:ident)) => {
+
+ };
+
+ (@vts: $adc_type:ident => ($common_type:ident)) => {
+ /// Check if the internal temperature sensor channel is enabled.
+ pub fn is_temperature_enabled(&self) -> bool {
+ self.adc_common.ccr.read().ch17sel().bit_is_set()
+ }
+
+ /// Enable the internal temperature sensor channel.
+ ///
+ /// Returns `Some(Temperature)` if the channel was enabled or `None` if it was already enabled before.
+ pub fn enable_temperature(&mut self, delay: &mut impl DelayUs) -> Option {
+ if self.is_temperature_enabled() {
+ return None
+ }
+
+ self.adc_common.ccr.modify(|_, w| w.ch17sel().set_bit());
+
+ // FIXME: This note from the reference manual is currently not possible
+ // rm0351 section 18.4.32 pg580 (L47/L48/L49/L4A models)
+ // Note:
+ // The sensor has a startup time after waking from power-down mode before it can output VTS
+ // at the correct level. The ADC also has a startup time after power-on, so to minimize the
+ // delay, the ADEN and CH17SEL bits should be set at the same time.
+ //
+ // https://github.com/STMicroelectronics/STM32CubeL4/blob/master/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h#L1363
+ // 120us is used in the ST HAL code
+ delay.delay_us(150);
+
+ Some(Temperature { _0: () })
+ }
+
+ /// Disable the internal temperature sensor channel.
+ pub fn disable_temperature(&mut self, temperature: Temperature) {
+ drop(temperature);
+
+ self.adc_common.ccr.modify(|_, w| w.ch17sel().clear_bit())
+ }
+ };
+
+ (@no_vts: $adc_type:ident => ($common_type:ident)) => {
+
+ };
+
+ // ADC1 supports VREF, VBAT and VTS.
+ (@additionals: ADC1 => ($common_type:ident)) => {
+ adc!(@vref: ADC1 => ($common_type));
+ adc!(@vbat: ADC1 => ($common_type));
+ adc!(@vts: ADC1 => ($common_type));
+ };
+
+ // ADC3 supports VBAT and VTS.
+ (@additionals: ADC3 => ($common_type:ident)) => {
+ adc!(@no_vref: ADC3 => ($common_type));
+ adc!(@vbat: ADC3 => ($common_type));
+ adc!(@vts: ADC3 => ($common_type));
+ };
+
+ (@additionals: $adc_type:ident => ($common_type:ident)) => {
+ adc!(@no_vref: $adc_type => ($common_type));
+ adc!(@no_vbat: $adc_type => ($common_type));
+ adc!(@no_vts: $adc_type => ($common_type));
+ };
+
+ ($($adc_type:ident => ($constructor_fn_name:ident, $common_type:ident)),+ $(,)?) => {
+ $(
+ impl Adc {
+ /// Enable the ADC clock and runs calibration.
+ pub fn $constructor_fn_name(
+ adc: pac::$adc_type,
+ adc_common: AdcCommon,
+ ccipr: &mut CCIPR,
+ delay: &mut impl DelayUs,
+ ) -> Self {
+ // Select system clock as ADC clock source
+ ccipr.ccipr().modify(|_, w| w.adcsel().sysclk());
+
+ // Initialize the ADC, according to the STM32L4xx Reference Manual,
+ // section 16.4.6.
+ adc.cr.write(|w| w.deeppwd().clear_bit()); // exit deep-power-down mode
+ adc.cr.modify(|_, w| w.advregen().set_bit()); // enable internal voltage regulator
+
+ // According to the STM32L4xx Reference Manual, section 16.4.6, we need
+ // to wait for T_ADCVREG_STUP after enabling the internal voltage
+ // regulator. For the STM32L433, this is 20 us. We choose 25 us to
+ // account for bad clocks.
+ delay.delay_us(25);
+
+ // Calibration procedure according to section 16.4.8.
+ adc.cr.modify(|_, w| {
+ w.adcal().set_bit(); // start calibration
+ w.adcaldif().clear_bit(); // single-ended mode
+
+ w
+ });
+
+ while adc.cr.read().adcal().bit_is_set() {}
+
+ // We need to wait 4 ADC clock after ADCAL goes low, 1 us is more than enough
+ delay.delay_us(1);
+
+ let mut s = Self {
+ adc,
+ adc_common,
+ resolution: Resolution::default(),
+ sample_time: SampleTime::default(),
+ calibrated_vdda: VDDA_CALIB_MV,
+ };
+
+ s.calibrate(delay);
+
+ s
+ }
+
+ adc!(@additionals: $adc_type => ($common_type));
+
+ /// Check if the ADC is enabled.
+ #[inline]
+ pub fn is_enabled(&self) -> bool {
+ self.adc.cr.read().aden().bit_is_set()
+ }
+
+ /// Enable the ADC.
+ #[inline]
+ pub fn enable(&mut self) {
+ if !self.is_enabled() {
+ // Make sure bits are off
+ while self.adc.cr.read().addis().bit_is_set() {}
+
+ // Clear ADRDY by setting it (See Reference Manual section 1.16.1)
+ self.adc.isr.modify(|_, w| w.adrdy().set_bit());
+ self.adc.cr.modify(|_, w| w.aden().set_bit());
+ while self.adc.isr.read().adrdy().bit_is_clear() {}
+
+ // Configure ADC
+ self.adc.cfgr.modify(|_, w| {
+ // This is sound, as all `Resolution` values are valid for this
+ // field.
+ unsafe { w.res().bits(self.resolution as u8) }
+ });
+ }
+ }
+
+ /// Disable the ADC.
+ #[inline]
+ pub fn disable(&mut self) {
+ self.adc.cr.modify(|_, w| w.addis().set_bit());
+ }
+
+ /// Returns the current sample stored in the ADC data register.
+ #[inline]
+ pub fn current_sample(&self) -> u16 {
+ // Sound, as bits 31:16 are reserved, read-only and 0 in ADC_DR
+ // TODO: Switch to using `rdata` once https://github.com/stm32-rs/stm32-rs/pull/723 is released.
+ self.adc.dr.read().bits() as u16
+ }
+
+ /// Configure the channel for a specific step in the sequence.
+ ///
+ /// Automatically sets the sequence length to the farthes sequence
+ /// index that has been used so far. Use [`Adc::reset_sequence`] to
+ /// reset the sequence length.
+ pub fn configure_sequence(
+ &mut self,
+ channel: &mut C,
+ sequence: Sequence,
+ sample_time: SampleTime,
+ ) where
+ C: Channel,
+ {
+ let channel_bits = C::channel();
+ channel.set_sample_time(&mut self.adc, sample_time);
+
+ unsafe {
+ // This is sound as channel() always returns a valid channel number
+ match sequence {
+ Sequence::One => self.adc.sqr1.modify(|_, w| w.sq1().bits(channel_bits)),
+ Sequence::Two => self.adc.sqr1.modify(|_, w| w.sq2().bits(channel_bits)),
+ Sequence::Three => self.adc.sqr1.modify(|_, w| w.sq3().bits(channel_bits)),
+ Sequence::Four => self.adc.sqr1.modify(|_, w| w.sq4().bits(channel_bits)),
+ Sequence::Five => self.adc.sqr2.modify(|_, w| w.sq5().bits(channel_bits)),
+ Sequence::Six => self.adc.sqr2.modify(|_, w| w.sq6().bits(channel_bits)),
+ Sequence::Seven => self.adc.sqr2.modify(|_, w| w.sq7().bits(channel_bits)),
+ Sequence::Eight => self.adc.sqr2.modify(|_, w| w.sq8().bits(channel_bits)),
+ Sequence::Nine => self.adc.sqr2.modify(|_, w| w.sq9().bits(channel_bits)),
+ Sequence::Ten => self.adc.sqr3.modify(|_, w| w.sq10().bits(channel_bits)),
+ Sequence::Eleven => self.adc.sqr3.modify(|_, w| w.sq11().bits(channel_bits)),
+ Sequence::Twelve => self.adc.sqr3.modify(|_, w| w.sq12().bits(channel_bits)),
+ Sequence::Thirteen => self.adc.sqr3.modify(|_, w| w.sq13().bits(channel_bits)),
+ Sequence::Fourteen => self.adc.sqr3.modify(|_, w| w.sq14().bits(channel_bits)),
+ Sequence::Fifteen => self.adc.sqr4.modify(|_, w| w.sq15().bits(channel_bits)),
+ Sequence::Sixteen => self.adc.sqr4.modify(|_, w| w.sq16().bits(channel_bits)),
+ }
+ }
+
+ // This will only ever extend the sequence, not shrink it.
+ let current_seql = self.get_sequence_length();
+ let next_seql: u8 = sequence.into();
+ if next_seql >= current_seql {
+ // Note: sequence length of 0 = 1 conversion
+ self.set_sequence_length(sequence.into());
+ }
+ }
+
+ /// Get the configured sequence length (= `actual sequence length - 1`)
+ #[inline]
+ pub(crate) fn get_sequence_length(&self) -> u8 {
+ self.adc.sqr1.read().l().bits()
+ }
+
+ /// Private: length must be `actual sequence length - 1`, so not API-friendly.
+ /// Use [`Adc::reset_sequence`] and [`Adc::configure_sequence`] instead
+ #[inline]
+ fn set_sequence_length(&mut self, length: u8) {
+ self.adc.sqr1.modify(|_, w| unsafe { w.l().bits(length) });
+ }
+
+ /// Reset the sequence length to 1
+ ///
+ /// Does *not* erase previously configured sequence settings, only
+ /// changes the sequence length
+ #[inline]
+ pub fn reset_sequence(&mut self) {
+ self.adc.sqr1.modify(|_, w| unsafe { w.l().bits(0b0000) })
+ }
+
+ #[inline]
+ pub fn has_completed_conversion(&self) -> bool {
+ self.adc.isr.read().eoc().bit_is_set()
+ }
+
+ #[inline]
+ pub fn has_completed_sequence(&self) -> bool {
+ self.adc.isr.read().eos().bit_is_set()
+ }
+
+ #[inline]
+ pub fn clear_end_flags(&mut self) {
+ // EOS and EOC are reset by setting them (See reference manual section 16.6.1)
+ self.adc
+ .isr
+ .modify(|_, w| w.eos().set_bit().eoc().set_bit());
+ }
+
+ #[inline]
+ pub fn start_conversion(&mut self) {
+ self.enable();
+ self.clear_end_flags();
+ self.adc.cr.modify(|_, w| w.adstart().set_bit());
+ }
+
+ #[inline]
+ pub fn is_converting(&self) -> bool {
+ self.adc.cr.read().adstart().bit_is_set()
+ }
+
+ #[inline]
+ pub fn listen(&mut self, event: Event) {
+ self.adc.ier.modify(|_, w| match event {
+ Event::EndOfRegularSequence => w.eosie().set_bit(),
+ Event::EndOfRegularConversion => w.eocie().set_bit(),
+ });
+ }
+
+ #[inline]
+ pub fn unlisten(&mut self, event: Event) {
+ self.adc.ier.modify(|_, w| match event {
+ Event::EndOfRegularSequence => w.eosie().clear_bit(),
+ Event::EndOfRegularConversion => w.eocie().clear_bit(),
+ });
+ }
+ }
+ )*
+ };
+}
+
+adc!(ADC1 => (adc1, ADC_COMMON));
+
+adc_pins!(
+ // “Table 25. Embedded internal voltage reference” in the STM32L496xx datasheet states that
+ // the sample time needs to be at least 4 us. With 640.5 ADC cycles at 80 MHz, we have a
+ // minimum of 8 us, leaving some headroom.
+ Vref => (ADC1, 0, smpr1, smp0, SampleTime::Cycles640_5),
+ gpio::PC0 => (ADC1, 1, smpr1, smp1),
+ gpio::PC1 => (ADC1, 2, smpr1, smp2),
+ gpio::PC2 => (ADC1, 3, smpr1, smp3),
+ gpio::PC3 => (ADC1, 4, smpr1, smp4),
+ gpio::PA0 => (ADC1, 5, smpr1, smp5),
+ gpio::PA1 => (ADC1, 6, smpr1, smp6),
+ gpio::PA2 => (ADC1, 7, smpr1, smp7),
+ gpio::PA3 => (ADC1, 8, smpr1, smp8),
+ gpio::PA4 => (ADC1, 9, smpr1, smp9),
+ gpio::PA5 => (ADC1, 10, smpr2, smp10),
+ gpio::PA6 => (ADC1, 11, smpr2, smp11),
+ gpio::PA7 => (ADC1, 12, smpr2, smp12),
+ gpio::PC4 => (ADC1, 13, smpr2, smp13),
+ gpio::PC5 => (ADC1, 14, smpr2, smp14),
+ gpio::PB0 => (ADC1, 15, smpr2, smp15),
+ gpio::PB1 => (ADC1, 16, smpr2, smp16),
+ Temperature => (ADC1, 17, smpr2, smp17),
+ Vbat => (ADC1, 18, smpr2, smp18),
+);
+
+#[cfg(not(any(
+ feature = "stm32l433",
+ feature = "stm32l443",
+ // feature = "stm32l4p5",
+ // feature = "stm32l4q5",
+ // feature = "stm32l4r5",
+ // feature = "stm32l4s5",
+ // feature = "stm32l4r7",
+ // feature = "stm32l4s7",
+ feature = "stm32l4r9",
+ feature = "stm32l4s9",
+)))]
+adc!(ADC2 => (adc2, ADC_COMMON));
+
+#[cfg(not(any(
+ feature = "stm32l433",
+ feature = "stm32l443",
+ // feature = "stm32l4p5",
+ // feature = "stm32l4q5",
+ // feature = "stm32l4r5",
+ // feature = "stm32l4s5",
+ // feature = "stm32l4r7",
+ // feature = "stm32l4s7",
+ feature = "stm32l4r9",
+ feature = "stm32l4s9",
+)))]
+adc_pins!(
+ gpio::PC0 => (ADC2, 1, smpr1, smp1),
+ gpio::PC1 => (ADC2, 2, smpr1, smp2),
+ gpio::PC2 => (ADC2, 3, smpr1, smp3),
+ gpio::PC3 => (ADC2, 4, smpr1, smp4),
+ gpio::PA0 => (ADC2, 5, smpr1, smp5),
+ gpio::PA1 => (ADC2, 6, smpr1, smp6),
+ gpio::PA2 => (ADC2, 7, smpr1, smp7),
+ gpio::PA3 => (ADC2, 8, smpr1, smp8),
+ gpio::PA4 => (ADC2, 9, smpr1, smp9),
+ gpio::PA5 => (ADC2, 10, smpr2, smp10),
+ gpio::PA6 => (ADC2, 11, smpr2, smp11),
+ gpio::PA7 => (ADC2, 12, smpr2, smp12),
+ gpio::PC4 => (ADC2, 13, smpr2, smp13),
+ gpio::PC5 => (ADC2, 14, smpr2, smp14),
+ gpio::PB0 => (ADC2, 15, smpr2, smp15),
+ gpio::PB1 => (ADC2, 16, smpr2, smp16),
+ // DAC1 => (ADC2, 17, smpr2, smp17),
+ // DAC2 => (ADC2, 18, smpr2, smp18),
+);
+
+#[cfg(any(
+ feature = "stm32l476",
+ feature = "stm32l486",
+ feature = "stm32l496",
+ feature = "stm32l4a6",
+))]
+adc!(ADC3 => (adc3, ADC_COMMON));
+
+#[cfg(any(
+ feature = "stm32l476",
+ feature = "stm32l486",
+ feature = "stm32l496",
+ feature = "stm32l4a6",
+))]
+adc_pins!(
+ gpio::PC0 => (ADC3, 1, smpr1, smp1),
+ gpio::PC1 => (ADC3, 2, smpr1, smp2),
+ gpio::PC2 => (ADC3, 3, smpr1, smp3),
+ gpio::PC3 => (ADC3, 4, smpr1, smp4),
+ gpio::PF3 => (ADC3, 6, smpr1, smp6),
+ gpio::PF4 => (ADC3, 7, smpr1, smp7),
+ gpio::PF5 => (ADC3, 8, smpr1, smp8),
+ gpio::PF6 => (ADC3, 9, smpr1, smp9),
+ gpio::PF7 => (ADC3, 10, smpr2, smp10),
+ gpio::PF8 => (ADC3, 11, smpr2, smp11),
+ gpio::PF9 => (ADC3, 12, smpr2, smp12),
+ gpio::PF10 => (ADC3, 13, smpr2, smp13),
+ // DAC1 => (ADC2, 14, smpr2, smp14),
+ // DAC2 => (ADC2, 15, smpr2, smp15),
+ Temperature => (ADC3, 17, smpr2, smp17),
+ Vbat => (ADC3, 18, smpr2, smp18),
+);
diff --git a/src/can.rs b/src/can.rs
index 44034f24..d06c8755 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,20 @@ 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 {
+ #[cfg(any(feature = "f4", feature = "f7"))]
const NUM_FILTER_BANKS: u8 = 28;
+ #[cfg(feature = "l4")]
+ const NUM_FILTER_BANKS: u8 = 14;
}
-unsafe impl bxcan::MasterInstance for Can {}
+unsafe impl bxcan::MasterInstance for Can {}
diff --git a/src/crc_l4.rs b/src/crc_l4.rs
new file mode 100644
index 00000000..e62fb53c
--- /dev/null
+++ b/src/crc_l4.rs
@@ -0,0 +1,205 @@
+//! CRC calculation unit
+//!
+//! Usage example:
+//! ```
+//! let crc = dp.CRC.constrain(&mut rcc.ahb1);
+//!
+//! // Lets use the CRC-16-CCITT polynomial
+//! let mut crc = crc.polynomial(crc::Polynomial::L16(0x1021)).freeze();
+//!
+//! let data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
+//! crc.feed(&data);
+//!
+//! let result = crc.result();
+//! assert!(result == 0x78cb);
+//! ```
+
+#![deny(missing_docs)]
+
+use crate::pac::CRC;
+use crate::rcc::{self, Enable};
+use core::hash::Hasher;
+
+/// Extension trait to constrain the CRC peripheral.
+pub trait CrcExt {
+ /// Constrains the CRC peripheral to play nicely with the other abstractions
+ fn constrain(self, ahb1: &mut rcc::AHB1) -> Config;
+}
+
+impl CrcExt for CRC {
+ fn constrain(self, ahb1: &mut rcc::AHB1) -> Config {
+ // Enable power to CRC unit
+ CRC::enable(ahb1);
+
+ // Default values
+ Config {
+ initial_value: 0xffff_ffff,
+ polynomial: Polynomial::L32(0x04c1_1db7),
+ input_bit_reversal: None,
+ output_bit_reversal: false,
+ }
+ }
+}
+
+/// Polynomial settings.
+pub enum Polynomial {
+ /// 7-bit polynomial, only the lowest 7 bits are valid
+ L7(u8),
+ /// 8-bit polynomial
+ L8(u8),
+ /// 16-bit polynomial
+ L16(u16),
+ /// 32-bit polynomial
+ L32(u32),
+}
+
+/// Bit reversal settings.
+pub enum BitReversal {
+ /// Reverse bits by byte
+ ByByte,
+ /// Reverse bits by half-word
+ ByHalfWord,
+ /// Reverse bits by word
+ ByWord,
+}
+
+/// CRC configuration structure, uses builder pattern.
+pub struct Config {
+ initial_value: u32,
+ polynomial: Polynomial,
+ input_bit_reversal: Option,
+ output_bit_reversal: bool,
+}
+
+impl Config {
+ /// Sets the initial value of the CRC.
+ pub fn initial_value(mut self, init: u32) -> Self {
+ self.initial_value = init;
+
+ self
+ }
+
+ /// Sets the polynomial of the CRC.
+ pub fn polynomial(mut self, polynomial: Polynomial) -> Self {
+ self.polynomial = polynomial;
+
+ self
+ }
+
+ /// Enables bit reversal of the inputs.
+ pub fn input_bit_reversal(mut self, rev: BitReversal) -> Self {
+ self.input_bit_reversal = Some(rev);
+
+ self
+ }
+
+ /// Enables bit reversal of the outputs.
+ pub fn output_bit_reversal(mut self, rev: bool) -> Self {
+ self.output_bit_reversal = rev;
+
+ self
+ }
+
+ /// Freezes the peripheral, making the configuration take effect.
+ pub fn freeze(self) -> Crc {
+ let crc = unsafe { &(*CRC::ptr()) };
+
+ let (poly, poly_bits, init) = match self.polynomial {
+ Polynomial::L7(val) => ((val & 0x7f) as u32, 0b11, self.initial_value & 0x7f),
+ Polynomial::L8(val) => (val as u32, 0b10, self.initial_value & 0xff),
+ Polynomial::L16(val) => (val as u32, 0b01, self.initial_value & 0xffff),
+ Polynomial::L32(val) => (val, 0b00, self.initial_value),
+ };
+
+ let in_rev_bits = match self.input_bit_reversal {
+ None => 0b00,
+ Some(BitReversal::ByByte) => 0b01,
+ Some(BitReversal::ByHalfWord) => 0b10,
+ Some(BitReversal::ByWord) => 0b11,
+ };
+
+ crc.init.write(|w| w.init().bits(init));
+ crc.pol.write(|w| w.bits(poly));
+ crc.cr.write(|w| {
+ w.rev_in().bits(in_rev_bits);
+ w.polysize().bits(poly_bits);
+ w.reset().set_bit();
+
+ if self.output_bit_reversal {
+ w.rev_out().set_bit()
+ } else {
+ w.rev_out().clear_bit()
+ }
+ });
+
+ Crc {}
+ }
+}
+
+/// Constrained CRC peripheral.
+pub struct Crc {}
+
+impl Crc {
+ /// This will reset the CRC to its initial condition.
+ #[inline]
+ pub fn reset(&mut self) {
+ let crc = unsafe { &(*CRC::ptr()) };
+
+ crc.cr.modify(|_, w| w.reset().set_bit());
+ }
+
+ /// This will reset the CRC to its initial condition, however with a specific initial value.
+ /// This is very useful if many task are sharing the CRC peripheral, as one can read out the
+ /// intermediate result, store it until the next time a task runs, and initialize with the
+ /// intermediate result to continue where the task left off.
+ #[inline]
+ pub fn reset_with_inital_value(&mut self, initial_value: u32) {
+ let crc = unsafe { &(*CRC::ptr()) };
+
+ crc.init.write(|w| w.init().bits(initial_value));
+ crc.cr.modify(|_, w| w.reset().set_bit());
+ }
+
+ /// Feed the CRC with data
+ #[inline]
+ pub fn feed(&mut self, data: &[u8]) {
+ let crc = unsafe { &(*CRC::ptr()) };
+ for &byte in data {
+ crc.dr8().write(|w| w.dr8().bits(byte));
+ }
+ }
+
+ /// Get the result of the CRC, depending on the polynomial chosen only a certain amount of the
+ /// bits are the result. This will reset the CRC peripheral after use.
+ #[inline]
+ pub fn result(&mut self) -> u32 {
+ let ret = self.peek_result();
+
+ self.reset();
+
+ ret
+ }
+
+ /// Get a peed at the result of the CRC, depending on the polynomial chosen only a certain
+ /// amount of the bits are the result.
+ #[inline]
+ pub fn peek_result(&self) -> u32 {
+ let crc = unsafe { &(*CRC::ptr()) };
+
+ crc.dr().read().bits()
+ }
+}
+
+impl Hasher for Crc {
+ #[inline]
+ fn finish(&self) -> u64 {
+ // `peek_result` as `core::hash::Hasher` required that the `finish` method does not reset
+ // the hasher.
+ self.peek_result() as u64
+ }
+
+ #[inline]
+ fn write(&mut self, data: &[u8]) {
+ self.feed(data);
+ }
+}
diff --git a/src/dma/traits.rs b/src/dma/traits.rs
index 1d74e5f6..29c62f19 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.
@@ -349,7 +351,109 @@ macro_rules! dma_map {
}
use dma_map;
+/*
+#[cfg(feature = "c0")]
+mod c0;
+#[allow(unused)]
+#[cfg(feature = "c0")]
+pub use c0::*;
+
+#[cfg(feature = "f0")]
+mod f0;
+#[allow(unused)]
+#[cfg(feature = "f0")]
+pub use f0::*;
+
+#[cfg(feature = "f2")]
+mod f2;
+#[allow(unused)]
+#[cfg(feature = "f2")]
+pub use f2::*;
+
+#[cfg(feature = "f3")]
+mod f3;
+#[allow(unused)]
+#[cfg(feature = "f3")]
+pub use f3::*;
+*/
+#[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 = "g0")]
+mod g0;
+#[allow(unused)]
+#[cfg(feature = "g0")]
+pub use g0::*;
+*/
+#[cfg(feature = "g4")]
+mod g4;
+#[allow(unused)]
+#[cfg(feature = "g4")]
+pub use g4::*;
+/*
+#[cfg(feature = "h7")]
+mod h7;
+#[allow(unused)]
+#[cfg(feature = "h7")]
+pub use h7::*;
+
+#[cfg(feature = "l0")]
+mod l0;
+#[allow(unused)]
+#[cfg(feature = "l0")]
+pub use l0::*;
+
+#[cfg(feature = "l1")]
+mod l1;
+#[allow(unused)]
+#[cfg(feature = "l1")]
+pub use l1::*;
+*/
+#[cfg(feature = "l4x")]
+mod l4;
+#[allow(unused)]
+#[cfg(feature = "l4x")]
+pub use l4::*;
+/*
+#[cfg(feature = "l4p")]
+mod l4p;
+#[allow(unused)]
+#[cfg(feature = "l4p")]
+pub use l4p::*;
+
+#[cfg(feature = "l5")]
+mod l5;
+#[allow(unused)]
+#[cfg(feature = "l5")]
+pub use l5::*;
+
+#[cfg(feature = "u5")]
+mod u5;
+#[allow(unused)]
+#[cfg(feature = "u5")]
+pub use u5::*;
+
+#[cfg(feature = "wl")]
+mod wl;
+#[allow(unused)]
+#[cfg(feature = "wl")]
+pub use wl::*;
+
+#[cfg(feature = "wb")]
+mod wb;
+#[allow(unused)]
+#[cfg(feature = "wb")]
+pub use wb::*;
+*/
#[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 00000000..73e176ed
--- /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