aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorbenjaminschlegel87 <[email protected]>2025-07-25 20:39:40 +0200
committerGitHub <[email protected]>2025-07-25 20:39:40 +0200
commitdbc1818acd69e2e15ac574356c9b07cb717df441 (patch)
tree05e6360c1946183b524a1ce82268547fe4bbcfd0 /embassy-stm32
parentadb728009ceba095d2190038ff698aaee08907a9 (diff)
parent996974e313fa5ec2c7c2d9dd0998fab244c0a180 (diff)
Merge branch 'embassy-rs:main' into stm32_adc_v3_hw_oversampling_support
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/Cargo.toml72
-rw-r--r--embassy-stm32/build.rs114
-rw-r--r--embassy-stm32/src/adc/adc4.rs (renamed from embassy-stm32/src/adc/u5_adc4.rs)104
-rw-r--r--embassy-stm32/src/adc/c0.rs3
-rw-r--r--embassy-stm32/src/adc/f3_v1_1.rs2
-rw-r--r--embassy-stm32/src/adc/g4.rs121
-rw-r--r--embassy-stm32/src/adc/mod.rs66
-rw-r--r--embassy-stm32/src/adc/v1.rs23
-rw-r--r--embassy-stm32/src/adc/v3.rs19
-rw-r--r--embassy-stm32/src/adc/v4.rs1
-rw-r--r--embassy-stm32/src/adc/watchdog_v1.rs188
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs327
-rw-r--r--embassy-stm32/src/can/common.rs111
-rw-r--r--embassy-stm32/src/can/enums.rs2
-rw-r--r--embassy-stm32/src/can/fd/message_ram/extended_filter.rs8
-rw-r--r--embassy-stm32/src/can/fd/message_ram/standard_filter.rs8
-rw-r--r--embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs18
-rw-r--r--embassy-stm32/src/can/fdcan.rs194
-rw-r--r--embassy-stm32/src/cordic/utils.rs2
-rw-r--r--embassy-stm32/src/cryp/mod.rs13
-rw-r--r--embassy-stm32/src/dac/mod.rs40
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs69
-rw-r--r--embassy-stm32/src/dma/gpdma.rs12
-rw-r--r--embassy-stm32/src/dma/util.rs6
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs10
-rw-r--r--embassy-stm32/src/flash/u5.rs26
-rw-r--r--embassy-stm32/src/hsem/mod.rs6
-rw-r--r--embassy-stm32/src/i2c/config.rs170
-rw-r--r--embassy-stm32/src/i2c/mod.rs173
-rw-r--r--embassy-stm32/src/i2c/v1.rs7
-rw-r--r--embassy-stm32/src/i2c/v2.rs729
-rw-r--r--embassy-stm32/src/ipcc.rs3
-rw-r--r--embassy-stm32/src/lib.rs27
-rw-r--r--embassy-stm32/src/low_power.rs9
-rw-r--r--embassy-stm32/src/lptim/timer/mod.rs50
-rw-r--r--embassy-stm32/src/macros.rs14
-rw-r--r--embassy-stm32/src/opamp.rs83
-rw-r--r--embassy-stm32/src/qspi/enums.rs16
-rw-r--r--embassy-stm32/src/qspi/mod.rs5
-rw-r--r--embassy-stm32/src/rcc/c0.rs2
-rw-r--r--embassy-stm32/src/rcc/hsi48.rs4
-rw-r--r--embassy-stm32/src/rcc/mco.rs2
-rw-r--r--embassy-stm32/src/rcc/mod.rs11
-rw-r--r--embassy-stm32/src/rcc/u5.rs165
-rw-r--r--embassy-stm32/src/rcc/wba.rs1
-rw-r--r--embassy-stm32/src/rtc/low_power.rs12
-rw-r--r--embassy-stm32/src/rtc/mod.rs4
-rw-r--r--embassy-stm32/src/rtc/v3.rs2
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs137
-rw-r--r--embassy-stm32/src/spi/mod.rs2
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs58
-rw-r--r--embassy-stm32/src/timer/input_capture.rs32
-rw-r--r--embassy-stm32/src/timer/mod.rs99
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs102
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs11
-rw-r--r--embassy-stm32/src/timer/qei.rs42
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs241
-rw-r--r--embassy-stm32/src/tsc/acquisition_banks.rs6
-rw-r--r--embassy-stm32/src/usart/buffered.rs2
-rw-r--r--embassy-stm32/src/usart/mod.rs18
-rw-r--r--embassy-stm32/src/usb/mod.rs28
-rw-r--r--embassy-stm32/src/usb/otg.rs29
-rw-r--r--embassy-stm32/src/usb/usb.rs68
64 files changed, 2829 insertions, 1101 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index b6781905e..c4c2cd013 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8## Unreleased 8## Unreleased
9- Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983)) 9- Modify BufferedUart initialization to take pins before interrupts ([#3983](https://github.com/embassy-rs/embassy/pull/3983))
10- Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125)) 10- Added a 'single-bank' and a 'dual-bank' feature so chips with configurable flash bank setups are be supported in embassy ([#4125](https://github.com/embassy-rs/embassy/pull/4125))
11- Add automatic setting of remap bits when using alternate DMA channels on STM32F0 and STM32F3 devices ([#3653](https://github.com/embassy-rs/embassy/pull/3653))
11 12
12## 0.2.0 - 2025-01-10 13## 0.2.0 - 2025-01-10
13 14
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 034f51df9..02e75733e 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -53,11 +53,11 @@ embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true }
53embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true } 53embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true }
54embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true } 54embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true }
55embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 55embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
56embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } 56embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
57embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false } 57embassy-embedded-hal = { version = "0.3.1", path = "../embassy-embedded-hal", default-features = false }
58embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } 58embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
59embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } 59embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" }
60embassy-usb-synopsys-otg = { version = "0.2.0", path = "../embassy-usb-synopsys-otg" } 60embassy-usb-synopsys-otg = { version = "0.3.0", path = "../embassy-usb-synopsys-otg" }
61embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true } 61embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true }
62 62
63embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 63embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
@@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false }
81sdio-host = "0.9.0" 81sdio-host = "0.9.0"
82critical-section = "1.1" 82critical-section = "1.1"
83#stm32-metapac = { version = "16" } 83#stm32-metapac = { version = "16" }
84stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } 84stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3" }
85 85
86vcell = "0.1.3" 86vcell = "0.1.3"
87nb = "1.0.0" 87nb = "1.0.0"
@@ -110,7 +110,7 @@ proc-macro2 = "1.0.36"
110quote = "1.0.15" 110quote = "1.0.15"
111 111
112#stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} 112#stm32-metapac = { version = "16", default-features = false, features = ["metadata"]}
113stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } 113stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9fc86ca7b3a8bc05182bf1ce3045602df1f5dce3", default-features = false, features = ["metadata"] }
114 114
115[features] 115[features]
116default = ["rt"] 116default = ["rt"]
@@ -129,6 +129,7 @@ defmt = [
129 "embassy-net-driver/defmt", 129 "embassy-net-driver/defmt",
130 "embassy-time?/defmt", 130 "embassy-time?/defmt",
131 "embassy-usb-synopsys-otg/defmt", 131 "embassy-usb-synopsys-otg/defmt",
132 "stm32-metapac/defmt"
132] 133]
133 134
134exti = [] 135exti = []
@@ -237,6 +238,47 @@ stm32c031g4 = [ "stm32-metapac/stm32c031g4" ]
237stm32c031g6 = [ "stm32-metapac/stm32c031g6" ] 238stm32c031g6 = [ "stm32-metapac/stm32c031g6" ]
238stm32c031k4 = [ "stm32-metapac/stm32c031k4" ] 239stm32c031k4 = [ "stm32-metapac/stm32c031k4" ]
239stm32c031k6 = [ "stm32-metapac/stm32c031k6" ] 240stm32c031k6 = [ "stm32-metapac/stm32c031k6" ]
241stm32c051c6 = [ "stm32-metapac/stm32c051c6" ]
242stm32c051c8 = [ "stm32-metapac/stm32c051c8" ]
243stm32c051d8 = [ "stm32-metapac/stm32c051d8" ]
244stm32c051f6 = [ "stm32-metapac/stm32c051f6" ]
245stm32c051f8 = [ "stm32-metapac/stm32c051f8" ]
246stm32c051g6 = [ "stm32-metapac/stm32c051g6" ]
247stm32c051g8 = [ "stm32-metapac/stm32c051g8" ]
248stm32c051k6 = [ "stm32-metapac/stm32c051k6" ]
249stm32c051k8 = [ "stm32-metapac/stm32c051k8" ]
250stm32c071c8 = [ "stm32-metapac/stm32c071c8" ]
251stm32c071cb = [ "stm32-metapac/stm32c071cb" ]
252stm32c071f8 = [ "stm32-metapac/stm32c071f8" ]
253stm32c071fb = [ "stm32-metapac/stm32c071fb" ]
254stm32c071g8 = [ "stm32-metapac/stm32c071g8" ]
255stm32c071gb = [ "stm32-metapac/stm32c071gb" ]
256stm32c071k8 = [ "stm32-metapac/stm32c071k8" ]
257stm32c071kb = [ "stm32-metapac/stm32c071kb" ]
258stm32c071r8 = [ "stm32-metapac/stm32c071r8" ]
259stm32c071rb = [ "stm32-metapac/stm32c071rb" ]
260stm32c091cb = [ "stm32-metapac/stm32c091cb" ]
261stm32c091cc = [ "stm32-metapac/stm32c091cc" ]
262stm32c091ec = [ "stm32-metapac/stm32c091ec" ]
263stm32c091fb = [ "stm32-metapac/stm32c091fb" ]
264stm32c091fc = [ "stm32-metapac/stm32c091fc" ]
265stm32c091gb = [ "stm32-metapac/stm32c091gb" ]
266stm32c091gc = [ "stm32-metapac/stm32c091gc" ]
267stm32c091kb = [ "stm32-metapac/stm32c091kb" ]
268stm32c091kc = [ "stm32-metapac/stm32c091kc" ]
269stm32c091rb = [ "stm32-metapac/stm32c091rb" ]
270stm32c091rc = [ "stm32-metapac/stm32c091rc" ]
271stm32c092cb = [ "stm32-metapac/stm32c092cb" ]
272stm32c092cc = [ "stm32-metapac/stm32c092cc" ]
273stm32c092ec = [ "stm32-metapac/stm32c092ec" ]
274stm32c092fb = [ "stm32-metapac/stm32c092fb" ]
275stm32c092fc = [ "stm32-metapac/stm32c092fc" ]
276stm32c092gb = [ "stm32-metapac/stm32c092gb" ]
277stm32c092gc = [ "stm32-metapac/stm32c092gc" ]
278stm32c092kb = [ "stm32-metapac/stm32c092kb" ]
279stm32c092kc = [ "stm32-metapac/stm32c092kc" ]
280stm32c092rb = [ "stm32-metapac/stm32c092rb" ]
281stm32c092rc = [ "stm32-metapac/stm32c092rc" ]
240stm32f030c6 = [ "stm32-metapac/stm32f030c6" ] 282stm32f030c6 = [ "stm32-metapac/stm32f030c6" ]
241stm32f030c8 = [ "stm32-metapac/stm32f030c8" ] 283stm32f030c8 = [ "stm32-metapac/stm32f030c8" ]
242stm32f030cc = [ "stm32-metapac/stm32f030cc" ] 284stm32f030cc = [ "stm32-metapac/stm32f030cc" ]
@@ -1634,6 +1676,24 @@ stm32wba55he = [ "stm32-metapac/stm32wba55he" ]
1634stm32wba55hg = [ "stm32-metapac/stm32wba55hg" ] 1676stm32wba55hg = [ "stm32-metapac/stm32wba55hg" ]
1635stm32wba55ue = [ "stm32-metapac/stm32wba55ue" ] 1677stm32wba55ue = [ "stm32-metapac/stm32wba55ue" ]
1636stm32wba55ug = [ "stm32-metapac/stm32wba55ug" ] 1678stm32wba55ug = [ "stm32-metapac/stm32wba55ug" ]
1679stm32wba62cg = [ "stm32-metapac/stm32wba62cg" ]
1680stm32wba62ci = [ "stm32-metapac/stm32wba62ci" ]
1681stm32wba62mg = [ "stm32-metapac/stm32wba62mg" ]
1682stm32wba62mi = [ "stm32-metapac/stm32wba62mi" ]
1683stm32wba62pg = [ "stm32-metapac/stm32wba62pg" ]
1684stm32wba62pi = [ "stm32-metapac/stm32wba62pi" ]
1685stm32wba63cg = [ "stm32-metapac/stm32wba63cg" ]
1686stm32wba63ci = [ "stm32-metapac/stm32wba63ci" ]
1687stm32wba64cg = [ "stm32-metapac/stm32wba64cg" ]
1688stm32wba64ci = [ "stm32-metapac/stm32wba64ci" ]
1689stm32wba65cg = [ "stm32-metapac/stm32wba65cg" ]
1690stm32wba65ci = [ "stm32-metapac/stm32wba65ci" ]
1691stm32wba65mg = [ "stm32-metapac/stm32wba65mg" ]
1692stm32wba65mi = [ "stm32-metapac/stm32wba65mi" ]
1693stm32wba65pg = [ "stm32-metapac/stm32wba65pg" ]
1694stm32wba65pi = [ "stm32-metapac/stm32wba65pi" ]
1695stm32wba65rg = [ "stm32-metapac/stm32wba65rg" ]
1696stm32wba65ri = [ "stm32-metapac/stm32wba65ri" ]
1637stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4", "_dual-core", "_core-cm4" ] 1697stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4", "_dual-core", "_core-cm4" ]
1638stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p", "_dual-core", "_core-cm0p" ] 1698stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p", "_dual-core", "_core-cm0p" ]
1639stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4", "_dual-core", "_core-cm4" ] 1699stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4", "_dual-core", "_core-cm4" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index bb5ef53d7..73860c64a 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -505,6 +505,13 @@ fn main() {
505 field: "CLK48SEL", 505 field: "CLK48SEL",
506 }, 506 },
507 ); 507 );
508 clock_gen.chained_muxes.insert(
509 "RFWKP",
510 &PeripheralRccRegister {
511 register: "CSR",
512 field: "RFWKPSEL",
513 },
514 );
508 } 515 }
509 if chip_name.starts_with("stm32f7") { 516 if chip_name.starts_with("stm32f7") {
510 clock_gen.chained_muxes.insert( 517 clock_gen.chained_muxes.insert(
@@ -1090,21 +1097,21 @@ fn main() {
1090 (("fmc", "CLK"), quote!(crate::fmc::ClkPin)), 1097 (("fmc", "CLK"), quote!(crate::fmc::ClkPin)),
1091 (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), 1098 (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
1092 (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), 1099 (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
1093 (("timer", "CH1"), quote!(crate::timer::Channel1Pin)), 1100 (("timer", "CH1"), quote!(crate::timer::TimerPin<Ch1>)),
1094 (("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)), 1101 (("timer", "CH1N"), quote!(crate::timer::TimerComplementaryPin<Ch1>)),
1095 (("timer", "CH2"), quote!(crate::timer::Channel2Pin)), 1102 (("timer", "CH2"), quote!(crate::timer::TimerPin<Ch2>)),
1096 (("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)), 1103 (("timer", "CH2N"), quote!(crate::timer::TimerComplementaryPin<Ch2>)),
1097 (("timer", "CH3"), quote!(crate::timer::Channel3Pin)), 1104 (("timer", "CH3"), quote!(crate::timer::TimerPin<Ch3>)),
1098 (("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)), 1105 (("timer", "CH3N"), quote!(crate::timer::TimerComplementaryPin<Ch3>)),
1099 (("timer", "CH4"), quote!(crate::timer::Channel4Pin)), 1106 (("timer", "CH4"), quote!(crate::timer::TimerPin<Ch4>)),
1100 (("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)), 1107 (("timer", "CH4N"), quote!(crate::timer::TimerComplementaryPin<Ch4>)),
1101 (("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)), 1108 (("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)),
1102 (("timer", "BKIN"), quote!(crate::timer::BreakInputPin)), 1109 (("timer", "BKIN"), quote!(crate::timer::BreakInputPin<BkIn1>)),
1103 (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), 1110 (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin<BkIn1>)),
1104 (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), 1111 (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin<BkIn1>)),
1105 (("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)), 1112 (("timer", "BKIN2"), quote!(crate::timer::BreakInputPin<BkIn2>)),
1106 (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)), 1113 (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInputComparator1Pin<BkIn2>)),
1107 (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)), 1114 (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInputComparator2Pin<BkIn2>)),
1108 (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)), 1115 (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)),
1109 (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)), 1116 (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)),
1110 (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)), 1117 (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)),
@@ -1402,31 +1409,24 @@ fn main() {
1402 } 1409 }
1403 1410
1404 if regs.kind == "opamp" { 1411 if regs.kind == "opamp" {
1405 if pin.signal.starts_with("VP") { 1412 let peri = format_ident!("{}", p.name);
1406 // Impl NonInvertingPin for the VP* signals (VP0, VP1, VP2, etc) 1413 let pin_name = format_ident!("{}", pin.pin);
1407 let peri = format_ident!("{}", p.name); 1414 if let Some(ch_str) = pin.signal.strip_prefix("VINP") {
1408 let pin_name = format_ident!("{}", pin.pin); 1415 // Impl NonInvertingPin for VINP0, VINP1 etc.
1409 let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap(); 1416 if let Ok(ch) = ch_str.parse::<u8>() {
1410 1417 g.extend(quote! {
1411 g.extend(quote! { 1418 impl_opamp_vp_pin!( #peri, #pin_name, #ch );
1412 impl_opamp_vp_pin!( #peri, #pin_name, #ch); 1419 });
1413 }) 1420 }
1414 } else if pin.signal.starts_with("VINM") { 1421 } else if let Some(ch_str) = pin.signal.strip_prefix("VINM") {
1415 // Impl NonInvertingPin for the VINM* signals ( VINM0, VINM1, etc) 1422 // Impl InvertingPin for VINM0, VINM1 etc.
1416 // STM32G4 1423 if let Ok(ch) = ch_str.parse::<u8>() {
1417 let peri = format_ident!("{}", p.name);
1418 let pin_name = format_ident!("{}", pin.pin);
1419 let ch: Result<u8, _> = pin.signal.strip_prefix("VINM").unwrap().parse();
1420
1421 if let Ok(ch) = ch {
1422 g.extend(quote! { 1424 g.extend(quote! {
1423 impl_opamp_vn_pin!( #peri, #pin_name, #ch); 1425 impl_opamp_vn_pin!( #peri, #pin_name, #ch);
1424 }) 1426 });
1425 } 1427 }
1426 } else if pin.signal == "VOUT" { 1428 } else if pin.signal == "VOUT" {
1427 // Impl OutputPin for the VOUT pin 1429 // Impl OutputPin for the VOUT pin
1428 let peri = format_ident!("{}", p.name);
1429 let pin_name = format_ident!("{}", pin.pin);
1430 g.extend(quote! { 1430 g.extend(quote! {
1431 impl_opamp_vout_pin!( #peri, #pin_name ); 1431 impl_opamp_vout_pin!( #peri, #pin_name );
1432 }) 1432 })
@@ -1482,10 +1482,10 @@ fn main() {
1482 (("hash", "IN"), quote!(crate::hash::Dma)), 1482 (("hash", "IN"), quote!(crate::hash::Dma)),
1483 (("cryp", "IN"), quote!(crate::cryp::DmaIn)), 1483 (("cryp", "IN"), quote!(crate::cryp::DmaIn)),
1484 (("cryp", "OUT"), quote!(crate::cryp::DmaOut)), 1484 (("cryp", "OUT"), quote!(crate::cryp::DmaOut)),
1485 (("timer", "CH1"), quote!(crate::timer::Ch1Dma)), 1485 (("timer", "CH1"), quote!(crate::timer::Dma<Ch1>)),
1486 (("timer", "CH2"), quote!(crate::timer::Ch2Dma)), 1486 (("timer", "CH2"), quote!(crate::timer::Dma<Ch2>)),
1487 (("timer", "CH3"), quote!(crate::timer::Ch3Dma)), 1487 (("timer", "CH3"), quote!(crate::timer::Dma<Ch3>)),
1488 (("timer", "CH4"), quote!(crate::timer::Ch4Dma)), 1488 (("timer", "CH4"), quote!(crate::timer::Dma<Ch4>)),
1489 (("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver 1489 (("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver
1490 (("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver 1490 (("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver
1491 ] 1491 ]
@@ -1497,6 +1497,10 @@ fn main() {
1497 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); 1497 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1498 } 1498 }
1499 1499
1500 if chip_name.starts_with("stm32wba") {
1501 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4));
1502 }
1503
1500 if chip_name.starts_with("stm32g4") { 1504 if chip_name.starts_with("stm32g4") {
1501 let line_number = chip_name.chars().skip(8).next().unwrap(); 1505 let line_number = chip_name.chars().skip(8).next().unwrap();
1502 if line_number == '3' || line_number == '4' { 1506 if line_number == '3' || line_number == '4' {
@@ -1554,9 +1558,35 @@ fn main() {
1554 quote!(()) 1558 quote!(())
1555 }; 1559 };
1556 1560
1561 let mut remap = quote!();
1562 for remap_info in ch.remap {
1563 let register = format_ident!("{}", remap_info.register.to_lowercase());
1564 let setter = format_ident!("set_{}", remap_info.field.to_lowercase());
1565
1566 let field_metadata = METADATA
1567 .peripherals
1568 .iter()
1569 .filter(|p| p.name == "SYSCFG")
1570 .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter())
1571 .filter(|f| f.name.eq_ignore_ascii_case(remap_info.register))
1572 .flat_map(|f| f.fields.iter())
1573 .find(|f| f.name.eq_ignore_ascii_case(remap_info.field))
1574 .unwrap();
1575
1576 let value = if field_metadata.bit_size == 1 {
1577 let bool_value = format_ident!("{}", remap_info.value > 0);
1578 quote!(#bool_value)
1579 } else {
1580 let value = remap_info.value;
1581 quote!(#value.into())
1582 };
1583
1584 remap.extend(quote!(crate::pac::SYSCFG.#register().modify(|w| w.#setter(#value));));
1585 }
1586
1557 let channel = format_ident!("{}", channel); 1587 let channel = format_ident!("{}", channel);
1558 g.extend(quote! { 1588 g.extend(quote! {
1559 dma_trait_impl!(#tr, #peri, #channel, #request); 1589 dma_trait_impl!(#tr, #peri, #channel, #request, {#remap});
1560 }); 1590 });
1561 } 1591 }
1562 } 1592 }
@@ -1888,9 +1918,9 @@ fn main() {
1888 } 1918 }
1889 1919
1890 g.extend(quote!( 1920 g.extend(quote!(
1891 pub fn gpio_block(n: usize) -> crate::pac::gpio::Gpio {{ 1921 pub fn gpio_block(n: usize) -> crate::pac::gpio::Gpio {
1892 unsafe {{ crate::pac::gpio::Gpio::from_ptr((#gpio_base + #gpio_stride*n) as _) }} 1922 unsafe { crate::pac::gpio::Gpio::from_ptr((#gpio_base + #gpio_stride*n) as _) }
1893 }} 1923 }
1894 )); 1924 ));
1895 1925
1896 // ======== 1926 // ========
diff --git a/embassy-stm32/src/adc/u5_adc4.rs b/embassy-stm32/src/adc/adc4.rs
index 1dd664366..31cbdc0d7 100644
--- a/embassy-stm32/src/adc/u5_adc4.rs
+++ b/embassy-stm32/src/adc/adc4.rs
@@ -1,10 +1,19 @@
1#[cfg(stm32u5)]
2use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingRatio as OversamplingRatio};
1#[allow(unused)] 3#[allow(unused)]
2use pac::adc::vals::{Adc4Dmacfg, Adc4Exten, Adc4OversamplingRatio}; 4#[cfg(stm32wba)]
5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel};
3 6
4use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel}; 7use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel};
5use crate::dma::Transfer; 8use crate::dma::Transfer;
6pub use crate::pac::adc::regs::Adc4Chselrmod0; 9#[cfg(stm32u5)]
10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr;
11#[cfg(stm32wba)]
12pub use crate::pac::adc::regs::Chselr;
13#[cfg(stm32u5)]
7pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime}; 14pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime};
15#[cfg(stm32wba)]
16pub use crate::pac::adc::vals::{Presc, Res as Resolution, SampleTime};
8use crate::time::Hertz; 17use crate::time::Hertz;
9use crate::{pac, rcc, Peri}; 18use crate::{pac, rcc, Peri};
10 19
@@ -67,12 +76,14 @@ impl<T: Instance> SealedAdcChannel<T> for Vcore {
67 } 76 }
68} 77}
69 78
79#[derive(Copy, Clone)]
70pub enum DacChannel { 80pub enum DacChannel {
71 OUT1, 81 OUT1,
72 OUT2, 82 OUT2,
73} 83}
74 84
75/// Number of samples used for averaging. 85/// Number of samples used for averaging.
86#[derive(Copy, Clone)]
76pub enum Averaging { 87pub enum Averaging {
77 Disabled, 88 Disabled,
78 Samples2, 89 Samples2,
@@ -178,7 +189,7 @@ pub struct Adc4<'d, T: Instance> {
178 adc: crate::Peri<'d, T>, 189 adc: crate::Peri<'d, T>,
179} 190}
180 191
181#[derive(Debug)] 192#[derive(Copy, Clone, Debug)]
182pub enum Adc4Error { 193pub enum Adc4Error {
183 InvalidSequence, 194 InvalidSequence,
184 DMAError, 195 DMAError,
@@ -242,17 +253,28 @@ impl<'d, T: Instance> Adc4<'d, T> {
242 fn configure(&mut self) { 253 fn configure(&mut self) {
243 // single conversion mode, software trigger 254 // single conversion mode, software trigger
244 T::regs().cfgr1().modify(|w| { 255 T::regs().cfgr1().modify(|w| {
256 #[cfg(stm32u5)]
245 w.set_cont(false); 257 w.set_cont(false);
258 #[cfg(stm32wba)]
259 w.set_cont(Cont::SINGLE);
246 w.set_discen(false); 260 w.set_discen(false);
247 w.set_exten(Adc4Exten::DISABLED); 261 w.set_exten(Exten::DISABLED);
262 #[cfg(stm32u5)]
248 w.set_chselrmod(false); 263 w.set_chselrmod(false);
264 #[cfg(stm32wba)]
265 w.set_chselrmod(Chselrmod::ENABLE_INPUT);
249 }); 266 });
250 267
251 // only use one channel at the moment 268 // only use one channel at the moment
252 T::regs().smpr().modify(|w| { 269 T::regs().smpr().modify(|w| {
270 #[cfg(stm32u5)]
253 for i in 0..24 { 271 for i in 0..24 {
254 w.set_smpsel(i, false); 272 w.set_smpsel(i, false);
255 } 273 }
274 #[cfg(stm32wba)]
275 for i in 0..14 {
276 w.set_smpsel(i, Smpsel::SMP1);
277 }
256 }); 278 });
257 } 279 }
258 280
@@ -275,6 +297,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
275 } 297 }
276 298
277 /// Enable reading the vbat internal channel. 299 /// Enable reading the vbat internal channel.
300 #[cfg(stm32u5)]
278 pub fn enable_vbat(&self) -> Vbat { 301 pub fn enable_vbat(&self) -> Vbat {
279 T::regs().ccr().modify(|w| { 302 T::regs().ccr().modify(|w| {
280 w.set_vbaten(true); 303 w.set_vbaten(true);
@@ -289,6 +312,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
289 } 312 }
290 313
291 /// Enable reading the vbat internal channel. 314 /// Enable reading the vbat internal channel.
315 #[cfg(stm32u5)]
292 pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac { 316 pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac {
293 let mux; 317 let mux;
294 match dac { 318 match dac {
@@ -317,17 +341,38 @@ impl<'d, T: Instance> Adc4<'d, T> {
317 } 341 }
318 342
319 /// Set hardware averaging. 343 /// Set hardware averaging.
344 #[cfg(stm32u5)]
345 pub fn set_averaging(&mut self, averaging: Averaging) {
346 let (enable, samples, right_shift) = match averaging {
347 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0),
348 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1),
349 Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, 2),
350 Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, 3),
351 Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, 4),
352 Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, 5),
353 Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, 6),
354 Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, 7),
355 Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, 8),
356 };
357
358 T::regs().cfgr2().modify(|w| {
359 w.set_ovsr(samples);
360 w.set_ovss(right_shift);
361 w.set_ovse(enable)
362 })
363 }
364 #[cfg(stm32wba)]
320 pub fn set_averaging(&mut self, averaging: Averaging) { 365 pub fn set_averaging(&mut self, averaging: Averaging) {
321 let (enable, samples, right_shift) = match averaging { 366 let (enable, samples, right_shift) = match averaging {
322 Averaging::Disabled => (false, Adc4OversamplingRatio::OVERSAMPLE2X, 0), 367 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0),
323 Averaging::Samples2 => (true, Adc4OversamplingRatio::OVERSAMPLE2X, 1), 368 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1),
324 Averaging::Samples4 => (true, Adc4OversamplingRatio::OVERSAMPLE4X, 2), 369 Averaging::Samples4 => (true, OversamplingRatio::OVERSAMPLE4X, Ovss::SHIFT2),
325 Averaging::Samples8 => (true, Adc4OversamplingRatio::OVERSAMPLE8X, 3), 370 Averaging::Samples8 => (true, OversamplingRatio::OVERSAMPLE8X, Ovss::SHIFT3),
326 Averaging::Samples16 => (true, Adc4OversamplingRatio::OVERSAMPLE16X, 4), 371 Averaging::Samples16 => (true, OversamplingRatio::OVERSAMPLE16X, Ovss::SHIFT4),
327 Averaging::Samples32 => (true, Adc4OversamplingRatio::OVERSAMPLE32X, 5), 372 Averaging::Samples32 => (true, OversamplingRatio::OVERSAMPLE32X, Ovss::SHIFT5),
328 Averaging::Samples64 => (true, Adc4OversamplingRatio::OVERSAMPLE64X, 6), 373 Averaging::Samples64 => (true, OversamplingRatio::OVERSAMPLE64X, Ovss::SHIFT6),
329 Averaging::Samples128 => (true, Adc4OversamplingRatio::OVERSAMPLE128X, 7), 374 Averaging::Samples128 => (true, OversamplingRatio::OVERSAMPLE128X, Ovss::SHIFT7),
330 Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8), 375 Averaging::Samples256 => (true, OversamplingRatio::OVERSAMPLE256X, Ovss::SHIFT8),
331 }; 376 };
332 377
333 T::regs().cfgr2().modify(|w| { 378 T::regs().cfgr2().modify(|w| {
@@ -342,10 +387,20 @@ impl<'d, T: Instance> Adc4<'d, T> {
342 channel.setup(); 387 channel.setup();
343 388
344 // Select channel 389 // Select channel
345 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); 390 #[cfg(stm32wba)]
346 T::regs().chselrmod0().modify(|w| { 391 {
347 w.set_chsel(channel.channel() as usize, true); 392 T::regs().chselr().write_value(Chselr(0_u32));
348 }); 393 T::regs().chselr().modify(|w| {
394 w.set_chsel0(channel.channel() as usize, true);
395 });
396 }
397 #[cfg(stm32u5)]
398 {
399 T::regs().chselrmod0().write_value(Chselr(0_u32));
400 T::regs().chselrmod0().modify(|w| {
401 w.set_chsel(channel.channel() as usize, true);
402 });
403 }
349 404
350 // Reset interrupts 405 // Reset interrupts
351 T::regs().isr().modify(|reg| { 406 T::regs().isr().modify(|reg| {
@@ -415,13 +470,19 @@ impl<'d, T: Instance> Adc4<'d, T> {
415 470
416 T::regs().cfgr1().modify(|reg| { 471 T::regs().cfgr1().modify(|reg| {
417 reg.set_dmaen(true); 472 reg.set_dmaen(true);
418 reg.set_dmacfg(Adc4Dmacfg::ONE_SHOT); 473 reg.set_dmacfg(Dmacfg::ONE_SHOT);
474 #[cfg(stm32u5)]
419 reg.set_chselrmod(false); 475 reg.set_chselrmod(false);
476 #[cfg(stm32wba)]
477 reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
420 }); 478 });
421 479
422 // Verify and activate sequence 480 // Verify and activate sequence
423 let mut prev_channel: i16 = -1; 481 let mut prev_channel: i16 = -1;
424 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32)); 482 #[cfg(stm32wba)]
483 T::regs().chselr().write_value(Chselr(0_u32));
484 #[cfg(stm32u5)]
485 T::regs().chselrmod0().write_value(Chselr(0_u32));
425 for channel in sequence { 486 for channel in sequence {
426 let channel_num = channel.channel; 487 let channel_num = channel.channel;
427 if channel_num as i16 <= prev_channel { 488 if channel_num as i16 <= prev_channel {
@@ -429,6 +490,11 @@ impl<'d, T: Instance> Adc4<'d, T> {
429 }; 490 };
430 prev_channel = channel_num as i16; 491 prev_channel = channel_num as i16;
431 492
493 #[cfg(stm32wba)]
494 T::regs().chselr().modify(|w| {
495 w.set_chsel0(channel.channel as usize, true);
496 });
497 #[cfg(stm32u5)]
432 T::regs().chselrmod0().modify(|w| { 498 T::regs().chselrmod0().modify(|w| {
433 w.set_chsel(channel.channel as usize, true); 499 w.set_chsel(channel.channel as usize, true);
434 }); 500 });
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs
index 936ad7413..f5870801e 100644
--- a/embassy-stm32/src/adc/c0.rs
+++ b/embassy-stm32/src/adc/c0.rs
@@ -48,7 +48,7 @@ impl<T: Instance> SealedAdcChannel<T> for Temperature {
48 } 48 }
49} 49}
50 50
51#[derive(Debug)] 51#[derive(Copy, Clone, Debug)]
52pub enum Prescaler { 52pub enum Prescaler {
53 NotDivided, 53 NotDivided,
54 DividedBy2, 54 DividedBy2,
@@ -138,6 +138,7 @@ impl<'a> defmt::Format for Prescaler {
138/// Number of samples used for averaging. 138/// Number of samples used for averaging.
139/// TODO: Implement hardware averaging setting. 139/// TODO: Implement hardware averaging setting.
140#[allow(unused)] 140#[allow(unused)]
141#[derive(Copy, Clone)]
141pub enum Averaging { 142pub enum Averaging {
142 Disabled, 143 Disabled,
143 Samples2, 144 Samples2,
diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs
index 944e971bb..84613078c 100644
--- a/embassy-stm32/src/adc/f3_v1_1.rs
+++ b/embassy-stm32/src/adc/f3_v1_1.rs
@@ -17,6 +17,7 @@ pub const VDDA_CALIB_MV: u32 = 3300;
17pub const ADC_MAX: u32 = (1 << 12) - 1; 17pub const ADC_MAX: u32 = (1 << 12) - 1;
18pub const VREF_INT: u32 = 1230; 18pub const VREF_INT: u32 = 1230;
19 19
20#[derive(Copy, Clone)]
20pub enum AdcPowerMode { 21pub enum AdcPowerMode {
21 AlwaysOn, 22 AlwaysOn,
22 DelayOff, 23 DelayOff,
@@ -24,6 +25,7 @@ pub enum AdcPowerMode {
24 DelayIdleOff, 25 DelayIdleOff,
25} 26}
26 27
28#[derive(Copy, Clone)]
27pub enum Prescaler { 29pub enum Prescaler {
28 Div1, 30 Div1,
29 Div2, 31 Div2,
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 1fce3085a..43498966f 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -24,44 +24,31 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
24#[cfg(stm32h7)] 24#[cfg(stm32h7)]
25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); 25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
26 26
27#[cfg(stm32g4)]
28const VREF_CHANNEL: u8 = 18;
29#[cfg(stm32g4)]
30const TEMP_CHANNEL: u8 = 16;
31
32#[cfg(stm32h7)]
33const VREF_CHANNEL: u8 = 19;
34#[cfg(stm32h7)]
35const TEMP_CHANNEL: u8 = 18;
36
37// TODO this should be 14 for H7a/b/35
38const VBAT_CHANNEL: u8 = 17;
39
40// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs 27// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
41/// Internal voltage reference channel. 28/// Internal voltage reference channel.
42pub struct VrefInt; 29pub struct VrefInt;
43impl<T: Instance> AdcChannel<T> for VrefInt {} 30impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {}
44impl<T: Instance> super::SealedAdcChannel<T> for VrefInt { 31impl<T: Instance + VrefChannel> super::SealedAdcChannel<T> for VrefInt {
45 fn channel(&self) -> u8 { 32 fn channel(&self) -> u8 {
46 VREF_CHANNEL 33 T::CHANNEL
47 } 34 }
48} 35}
49 36
50/// Internal temperature channel. 37/// Internal temperature channel.
51pub struct Temperature; 38pub struct Temperature;
52impl<T: Instance> AdcChannel<T> for Temperature {} 39impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {}
53impl<T: Instance> super::SealedAdcChannel<T> for Temperature { 40impl<T: Instance + TemperatureChannel> super::SealedAdcChannel<T> for Temperature {
54 fn channel(&self) -> u8 { 41 fn channel(&self) -> u8 {
55 TEMP_CHANNEL 42 T::CHANNEL
56 } 43 }
57} 44}
58 45
59/// Internal battery voltage channel. 46/// Internal battery voltage channel.
60pub struct Vbat; 47pub struct Vbat;
61impl<T: Instance> AdcChannel<T> for Vbat {} 48impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {}
62impl<T: Instance> super::SealedAdcChannel<T> for Vbat { 49impl<T: Instance + VBatChannel> super::SealedAdcChannel<T> for Vbat {
63 fn channel(&self) -> u8 { 50 fn channel(&self) -> u8 {
64 VBAT_CHANNEL 51 T::CHANNEL
65 } 52 }
66} 53}
67 54
@@ -234,7 +221,10 @@ impl<'d, T: Instance> Adc<'d, T> {
234 } 221 }
235 222
236 /// Enable reading the voltage reference internal channel. 223 /// Enable reading the voltage reference internal channel.
237 pub fn enable_vrefint(&self) -> VrefInt { 224 pub fn enable_vrefint(&self) -> VrefInt
225 where
226 T: VrefChannel,
227 {
238 T::common_regs().ccr().modify(|reg| { 228 T::common_regs().ccr().modify(|reg| {
239 reg.set_vrefen(true); 229 reg.set_vrefen(true);
240 }); 230 });
@@ -243,7 +233,10 @@ impl<'d, T: Instance> Adc<'d, T> {
243 } 233 }
244 234
245 /// Enable reading the temperature internal channel. 235 /// Enable reading the temperature internal channel.
246 pub fn enable_temperature(&self) -> Temperature { 236 pub fn enable_temperature(&self) -> Temperature
237 where
238 T: TemperatureChannel,
239 {
247 T::common_regs().ccr().modify(|reg| { 240 T::common_regs().ccr().modify(|reg| {
248 reg.set_vsenseen(true); 241 reg.set_vsenseen(true);
249 }); 242 });
@@ -252,7 +245,10 @@ impl<'d, T: Instance> Adc<'d, T> {
252 } 245 }
253 246
254 /// Enable reading the vbat internal channel. 247 /// Enable reading the vbat internal channel.
255 pub fn enable_vbat(&self) -> Vbat { 248 pub fn enable_vbat(&self) -> Vbat
249 where
250 T: VBatChannel,
251 {
256 T::common_regs().ccr().modify(|reg| { 252 T::common_regs().ccr().modify(|reg| {
257 reg.set_vbaten(true); 253 reg.set_vbaten(true);
258 }); 254 });
@@ -519,3 +515,78 @@ impl<'d, T: Instance> Adc<'d, T> {
519 } 515 }
520 } 516 }
521} 517}
518
519/// Implemented for ADCs that have a Temperature channel
520pub trait TemperatureChannel {
521 const CHANNEL: u8;
522}
523/// Implemented for ADCs that have a Vref channel
524pub trait VrefChannel {
525 const CHANNEL: u8;
526}
527/// Implemented for ADCs that have a VBat channel
528pub trait VBatChannel {
529 const CHANNEL: u8;
530}
531
532#[cfg(stm32g4)]
533mod g4 {
534 pub use super::*;
535
536 impl TemperatureChannel for crate::peripherals::ADC1 {
537 const CHANNEL: u8 = 16;
538 }
539
540 impl VrefChannel for crate::peripherals::ADC1 {
541 const CHANNEL: u8 = 18;
542 }
543
544 impl VBatChannel for crate::peripherals::ADC1 {
545 const CHANNEL: u8 = 17;
546 }
547
548 #[cfg(peri_adc3_common)]
549 impl VrefChannel for crate::peripherals::ADC3 {
550 const CHANNEL: u8 = 18;
551 }
552
553 #[cfg(peri_adc3_common)]
554 impl VBatChannel for crate::peripherals::ADC3 {
555 const CHANNEL: u8 = 17;
556 }
557
558 #[cfg(not(stm32g4x1))]
559 impl VrefChannel for crate::peripherals::ADC4 {
560 const CHANNEL: u8 = 18;
561 }
562
563 #[cfg(not(stm32g4x1))]
564 impl TemperatureChannel for crate::peripherals::ADC5 {
565 const CHANNEL: u8 = 4;
566 }
567
568 #[cfg(not(stm32g4x1))]
569 impl VrefChannel for crate::peripherals::ADC5 {
570 const CHANNEL: u8 = 18;
571 }
572
573 #[cfg(not(stm32g4x1))]
574 impl VBatChannel for crate::peripherals::ADC5 {
575 const CHANNEL: u8 = 17;
576 }
577}
578
579// TODO this should look at each ADC individually and impl the correct channels
580#[cfg(stm32h7)]
581mod h7 {
582 impl<T: Instance> TemperatureChannel for T {
583 const CHANNEL: u8 = 18;
584 }
585 impl<T: Instance> VrefChannel for T {
586 const CHANNEL: u8 = 19;
587 }
588 impl<T: Instance> VBatChannel for T {
589 // TODO this should be 14 for H7a/b/35
590 const CHANNEL: u8 = 17;
591 }
592}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index f46e87f38..778edc6f6 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -4,7 +4,7 @@
4#![allow(missing_docs)] // TODO 4#![allow(missing_docs)] // TODO
5#![cfg_attr(adc_f3_v2, allow(unused))] 5#![cfg_attr(adc_f3_v2, allow(unused))]
6 6
7#[cfg(not(any(adc_f3_v2)))] 7#[cfg(not(any(adc_f3_v2, adc_wba)))]
8#[cfg_attr(adc_f1, path = "f1.rs")] 8#[cfg_attr(adc_f1, path = "f1.rs")]
9#[cfg_attr(adc_f3, path = "f3.rs")] 9#[cfg_attr(adc_f3, path = "f3.rs")]
10#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")] 10#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
@@ -20,14 +20,14 @@ mod _version;
20use core::marker::PhantomData; 20use core::marker::PhantomData;
21 21
22#[allow(unused)] 22#[allow(unused)]
23#[cfg(not(any(adc_f3_v2)))] 23#[cfg(not(any(adc_f3_v2, adc_wba)))]
24pub use _version::*; 24pub use _version::*;
25use embassy_hal_internal::{impl_peripheral, PeripheralType}; 25use embassy_hal_internal::{impl_peripheral, PeripheralType};
26#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] 26#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
27use embassy_sync::waitqueue::AtomicWaker; 27use embassy_sync::waitqueue::AtomicWaker;
28 28
29#[cfg(adc_u5)] 29#[cfg(any(adc_u5, adc_wba))]
30#[path = "u5_adc4.rs"] 30#[path = "adc4.rs"]
31pub mod adc4; 31pub mod adc4;
32 32
33pub use crate::pac::adc::vals; 33pub use crate::pac::adc::vals;
@@ -36,15 +36,18 @@ pub use crate::pac::adc::vals::Res as Resolution;
36pub use crate::pac::adc::vals::SampleTime; 36pub use crate::pac::adc::vals::SampleTime;
37use crate::peripherals; 37use crate::peripherals;
38 38
39#[cfg(not(adc_wba))]
39dma_trait!(RxDma, Instance); 40dma_trait!(RxDma, Instance);
40#[cfg(adc_u5)] 41#[cfg(adc_u5)]
41dma_trait!(RxDma4, adc4::Instance); 42dma_trait!(RxDma4, adc4::Instance);
43#[cfg(adc_wba)]
44dma_trait!(RxDma4, adc4::Instance);
42 45
43/// Analog to Digital driver. 46/// Analog to Digital driver.
44pub struct Adc<'d, T: Instance> { 47pub struct Adc<'d, T: Instance> {
45 #[allow(unused)] 48 #[allow(unused)]
46 adc: crate::Peri<'d, T>, 49 adc: crate::Peri<'d, T>,
47 #[cfg(not(any(adc_f3_v2, adc_f3_v1_1)))] 50 #[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))]
48 sample_time: SampleTime, 51 sample_time: SampleTime,
49} 52}
50 53
@@ -63,6 +66,7 @@ impl State {
63} 66}
64 67
65trait SealedInstance { 68trait SealedInstance {
69 #[cfg(not(adc_wba))]
66 #[allow(unused)] 70 #[allow(unused)]
67 fn regs() -> crate::pac::adc::Adc; 71 fn regs() -> crate::pac::adc::Adc;
68 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] 72 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
@@ -73,7 +77,7 @@ trait SealedInstance {
73} 77}
74 78
75pub(crate) trait SealedAdcChannel<T> { 79pub(crate) trait SealedAdcChannel<T> {
76 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] 80 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
77 fn setup(&mut self) {} 81 fn setup(&mut self) {}
78 82
79 #[allow(unused)] 83 #[allow(unused)]
@@ -110,7 +114,8 @@ pub(crate) fn blocking_delay_us(us: u32) {
110 adc_h5, 114 adc_h5,
111 adc_h7rs, 115 adc_h7rs,
112 adc_u5, 116 adc_u5,
113 adc_c0 117 adc_c0,
118 adc_wba,
114)))] 119)))]
115#[allow(private_bounds)] 120#[allow(private_bounds)]
116pub trait Instance: SealedInstance + crate::PeripheralType { 121pub trait Instance: SealedInstance + crate::PeripheralType {
@@ -132,7 +137,8 @@ pub trait Instance: SealedInstance + crate::PeripheralType {
132 adc_h5, 137 adc_h5,
133 adc_h7rs, 138 adc_h7rs,
134 adc_u5, 139 adc_u5,
135 adc_c0 140 adc_c0,
141 adc_wba,
136))] 142))]
137#[allow(private_bounds)] 143#[allow(private_bounds)]
138pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { 144pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral {
@@ -144,7 +150,7 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
144pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized { 150pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
145 #[allow(unused_mut)] 151 #[allow(unused_mut)]
146 fn degrade_adc(mut self) -> AnyAdcChannel<T> { 152 fn degrade_adc(mut self) -> AnyAdcChannel<T> {
147 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] 153 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
148 self.setup(); 154 self.setup();
149 155
150 AnyAdcChannel { 156 AnyAdcChannel {
@@ -176,6 +182,36 @@ impl<T> AnyAdcChannel<T> {
176 self.channel 182 self.channel
177 } 183 }
178} 184}
185#[cfg(adc_wba)]
186foreach_adc!(
187 (ADC4, $common_inst:ident, $clock:ident) => {
188 impl crate::adc::adc4::SealedInstance for peripherals::ADC4 {
189 fn regs() -> crate::pac::adc::Adc4 {
190 crate::pac::ADC4
191 }
192 }
193
194 impl crate::adc::adc4::Instance for peripherals::ADC4 {
195 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
196 }
197 };
198
199 ($inst:ident, $common_inst:ident, $clock:ident) => {
200 impl crate::adc::SealedInstance for peripherals::$inst {
201 fn regs() -> crate::pac::adc::Adc {
202 crate::pac::$inst
203 }
204
205 fn common_regs() -> crate::pac::adccommon::AdcCommon {
206 return crate::pac::$common_inst
207 }
208 }
209
210 impl crate::adc::Instance for peripherals::$inst {
211 type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
212 }
213 };
214);
179 215
180#[cfg(adc_u5)] 216#[cfg(adc_u5)]
181foreach_adc!( 217foreach_adc!(
@@ -208,15 +244,21 @@ foreach_adc!(
208 }; 244 };
209); 245);
210 246
211#[cfg(not(adc_u5))] 247#[cfg(not(any(adc_u5, adc_wba)))]
212foreach_adc!( 248foreach_adc!(
213 ($inst:ident, $common_inst:ident, $clock:ident) => { 249 ($inst:ident, $common_inst:ident, $clock:ident) => {
214 impl crate::adc::SealedInstance for peripherals::$inst { 250 impl crate::adc::SealedInstance for peripherals::$inst {
251 #[cfg(not(adc_wba))]
215 fn regs() -> crate::pac::adc::Adc { 252 fn regs() -> crate::pac::adc::Adc {
216 crate::pac::$inst 253 crate::pac::$inst
217 } 254 }
218 255
219 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] 256 #[cfg(adc_wba)]
257 fn regs() -> crate::pac::adc::Adc4 {
258 crate::pac::$inst
259 }
260
261 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))]
220 fn common_regs() -> crate::pac::adccommon::AdcCommon { 262 fn common_regs() -> crate::pac::adccommon::AdcCommon {
221 return crate::pac::$common_inst 263 return crate::pac::$common_inst
222 } 264 }
@@ -238,7 +280,7 @@ macro_rules! impl_adc_pin {
238 ($inst:ident, $pin:ident, $ch:expr) => { 280 ($inst:ident, $pin:ident, $ch:expr) => {
239 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {} 281 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
240 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> { 282 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
241 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))] 283 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
242 fn setup(&mut self) { 284 fn setup(&mut self) {
243 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self); 285 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
244 } 286 }
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index fb6f5b7d0..7fe502da0 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -11,6 +11,9 @@ use crate::interrupt::typelevel::Interrupt;
11use crate::peripherals::ADC1; 11use crate::peripherals::ADC1;
12use crate::{interrupt, rcc, Peri}; 12use crate::{interrupt, rcc, Peri};
13 13
14mod watchdog_v1;
15pub use watchdog_v1::WatchdogChannels;
16
14pub const VDDA_CALIB_MV: u32 = 3300; 17pub const VDDA_CALIB_MV: u32 = 3300;
15pub const VREF_INT: u32 = 1230; 18pub const VREF_INT: u32 = 1230;
16 19
@@ -21,8 +24,15 @@ pub struct InterruptHandler<T: Instance> {
21 24
22impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 25impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
23 unsafe fn on_interrupt() { 26 unsafe fn on_interrupt() {
24 if T::regs().isr().read().eoc() { 27 let isr = T::regs().isr().read();
28 let ier = T::regs().ier().read();
29 if ier.eocie() && isr.eoc() {
30 // eocie is set during adc.read()
25 T::regs().ier().modify(|w| w.set_eocie(false)); 31 T::regs().ier().modify(|w| w.set_eocie(false));
32 } else if ier.awdie() && isr.awd() {
33 // awdie is set during adc.monitor_watchdog()
34 T::regs().cr().read().set_adstp(true);
35 T::regs().ier().modify(|w| w.set_awdie(false));
26 } else { 36 } else {
27 return; 37 return;
28 } 38 }
@@ -186,16 +196,21 @@ impl<'d, T: Instance> Adc<'d, T> {
186 196
187 T::regs().dr().read().data() 197 T::regs().dr().read().data()
188 } 198 }
189}
190 199
191impl<'d, T: Instance> Drop for Adc<'d, T> { 200 fn teardown_adc() {
192 fn drop(&mut self) {
193 // A.7.3 ADC disable code example 201 // A.7.3 ADC disable code example
194 T::regs().cr().modify(|reg| reg.set_adstp(true)); 202 T::regs().cr().modify(|reg| reg.set_adstp(true));
195 while T::regs().cr().read().adstp() {} 203 while T::regs().cr().read().adstp() {}
196 204
197 T::regs().cr().modify(|reg| reg.set_addis(true)); 205 T::regs().cr().modify(|reg| reg.set_addis(true));
198 while T::regs().cr().read().aden() {} 206 while T::regs().cr().read().aden() {}
207 }
208}
209
210impl<'d, T: Instance> Drop for Adc<'d, T> {
211 fn drop(&mut self) {
212 Self::teardown_adc();
213 Self::teardown_awd();
199 214
200 rcc::disable::<T>(); 215 rcc::disable::<T>();
201 } 216 }
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 7b5df80b8..805dae564 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,5 +1,7 @@
1use cfg_if::cfg_if; 1use cfg_if::cfg_if;
2use pac::adc::vals::Dmacfg; 2use pac::adc::vals::Dmacfg;
3#[cfg(adc_v3)]
4use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs};
3 5
4use super::{ 6use super::{
5 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, 7 blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel,
@@ -506,6 +508,23 @@ impl<'d, T: Instance> Adc<'d, T> {
506 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable)); 508 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
507 } 509 }
508 510
511 #[cfg(adc_v3)]
512 pub fn enable_regular_oversampling_mode(&mut self, mode: Rovsm, trig_mode: Trovs, enable: bool) {
513 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
514 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
515 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
516 }
517
518 #[cfg(adc_v3)]
519 pub fn set_oversampling_ratio(&mut self, ratio: OversamplingRatio) {
520 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
521 }
522
523 #[cfg(adc_v3)]
524 pub fn set_oversampling_shift(&mut self, shift: OversamplingShift) {
525 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
526 }
527
509 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { 528 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
510 cfg_if! { 529 cfg_if! {
511 if #[cfg(any(adc_g0, adc_u0))] { 530 if #[cfg(any(adc_g0, adc_u0))] {
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 39e0d51b9..b0871019a 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -142,6 +142,7 @@ impl Prescaler {
142} 142}
143 143
144/// Number of samples used for averaging. 144/// Number of samples used for averaging.
145#[derive(Copy, Clone)]
145pub enum Averaging { 146pub enum Averaging {
146 Disabled, 147 Disabled,
147 Samples2, 148 Samples2,
diff --git a/embassy-stm32/src/adc/watchdog_v1.rs b/embassy-stm32/src/adc/watchdog_v1.rs
new file mode 100644
index 000000000..bbe8e1971
--- /dev/null
+++ b/embassy-stm32/src/adc/watchdog_v1.rs
@@ -0,0 +1,188 @@
1use core::future::poll_fn;
2use core::task::Poll;
3
4use stm32_metapac::adc::vals::{Align, Awdsgl, Res};
5
6use crate::adc::{Adc, AdcChannel, Instance};
7
8/// This enum is passed into `Adc::init_watchdog` to specify the channels for the watchdog to monitor
9pub enum WatchdogChannels {
10 // Single channel identified by index
11 Single(u8),
12 // Multiple channels identified by mask
13 Multiple(u16),
14}
15
16impl WatchdogChannels {
17 pub fn from_channel<T>(channel: &impl AdcChannel<T>) -> Self {
18 Self::Single(channel.channel())
19 }
20
21 pub fn add_channel<T>(self, channel: &impl AdcChannel<T>) -> Self {
22 WatchdogChannels::Multiple(
23 (match self {
24 WatchdogChannels::Single(ch) => 1 << ch,
25 WatchdogChannels::Multiple(ch) => ch,
26 }) | 1 << channel.channel(),
27 )
28 }
29}
30
31impl<'d, T: Instance> Adc<'d, T> {
32 /// Configure the analog window watchdog to monitor one or more ADC channels
33 ///
34 /// `high_threshold` and `low_threshold` are expressed in the same way as ADC results. The format
35 /// depends on the values of CFGR1.ALIGN and CFGR1.RES.
36 pub fn init_watchdog(&mut self, channels: WatchdogChannels, low_threshold: u16, high_threshold: u16) {
37 Self::stop_awd();
38
39 match channels {
40 WatchdogChannels::Single(ch) => {
41 T::regs().chselr().modify(|w| {
42 w.set_chsel_x(ch.into(), true);
43 });
44 T::regs().cfgr1().modify(|w| {
45 w.set_awdch(ch);
46 w.set_awdsgl(Awdsgl::SINGLE_CHANNEL)
47 });
48 }
49 WatchdogChannels::Multiple(ch) => {
50 T::regs().chselr().modify(|w| w.0 = ch.into());
51 T::regs().cfgr1().modify(|w| {
52 w.set_awdch(0);
53 w.set_awdsgl(Awdsgl::ALL_CHANNELS)
54 });
55 }
56 }
57
58 Self::set_watchdog_thresholds(low_threshold, high_threshold);
59 Self::setup_awd();
60 }
61
62 /// Monitor the voltage on the selected channels; return when it crosses the thresholds.
63 ///
64 /// ```rust,ignore
65 /// // Wait for pin to go high
66 /// adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F);
67 /// let v_high = adc.monitor_watchdog().await;
68 /// info!("ADC sample is high {}", v_high);
69 /// ```
70 pub async fn monitor_watchdog(&mut self) -> u16 {
71 assert!(
72 match T::regs().cfgr1().read().awdsgl() {
73 Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0,
74 Awdsgl::ALL_CHANNELS => T::regs().cfgr1().read().awdch() == 0,
75 },
76 "`set_channel` should be called before `monitor`",
77 );
78 assert!(T::regs().chselr().read().0 != 0);
79 T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into()));
80 Self::start_awd();
81
82 let sample = poll_fn(|cx| {
83 T::state().waker.register(cx.waker());
84
85 if T::regs().isr().read().awd() {
86 Poll::Ready(T::regs().dr().read().data())
87 } else {
88 Poll::Pending
89 }
90 })
91 .await;
92
93 self.stop_watchdog();
94 sample
95 }
96
97 /// Stop monitoring the selected channels
98 pub fn stop_watchdog(&mut self) {
99 Self::stop_awd();
100 }
101
102 fn set_watchdog_thresholds(low_threshold: u16, high_threshold: u16) {
103 // This function takes `high_threshold` and `low_threshold` in the same alignment and resolution
104 // as ADC results, and programs them into ADC_DR. Because ADC_DR is always right-aligned on 12 bits,
105 // some bit-shifting may be necessary. See more in table 47 §13.7.1 Analog Watchdog Comparison
106
107 // Verify that the thresholds are in the correct bit positions according to alignment and resolution
108 let threshold_mask = match (T::regs().cfgr1().read().align(), T::regs().cfgr1().read().res()) {
109 (Align::LEFT, Res::BITS6) => 0x00FC,
110 (Align::LEFT, Res::BITS8) => 0xFF00,
111 (Align::LEFT, Res::BITS10) => 0xFFC0,
112 (Align::LEFT, Res::BITS12) => 0xFFF0,
113 (Align::RIGHT, Res::BITS6) => 0x003F,
114 (Align::RIGHT, Res::BITS8) => 0x00FF,
115 (Align::RIGHT, Res::BITS10) => 0x03FF,
116 (Align::RIGHT, Res::BITS12) => 0x0FFF,
117 };
118 assert!(
119 high_threshold & !threshold_mask == 0,
120 "High threshold {:x} is invalid — only bits {:x} are allowed",
121 high_threshold,
122 threshold_mask
123 );
124 assert!(
125 low_threshold & !threshold_mask == 0,
126 "Low threshold {:x} is invalid — only bits {:x} are allowed",
127 low_threshold,
128 threshold_mask
129 );
130
131 T::regs().tr().modify(|w| {
132 w.set_lt(low_threshold << threshold_mask.leading_zeros() >> 4);
133 w.set_ht(high_threshold << threshold_mask.leading_zeros() >> 4);
134 })
135 }
136
137 fn setup_awd() {
138 // Configure AWD
139 assert!(!T::regs().cr().read().adstart());
140 T::regs().cfgr1().modify(|w| w.set_awden(true));
141 }
142
143 fn start_awd() {
144 // Clear AWD interrupt flag
145 while T::regs().isr().read().awd() {
146 T::regs().isr().modify(|regs| {
147 regs.set_awd(true);
148 })
149 }
150
151 // Enable AWD interrupt
152 assert!(!T::regs().cr().read().adstart());
153 T::regs().ier().modify(|w| {
154 w.set_eocie(false);
155 w.set_awdie(true)
156 });
157
158 // Start conversion
159 T::regs().cfgr1().modify(|w| w.set_cont(true));
160 T::regs().cr().modify(|w| w.set_adstart(true));
161 }
162
163 fn stop_awd() {
164 // Stop conversion
165 while T::regs().cr().read().addis() {}
166 if T::regs().cr().read().adstart() {
167 T::regs().cr().write(|x| x.set_adstp(true));
168 while T::regs().cr().read().adstp() {}
169 }
170 T::regs().cfgr1().modify(|w| w.set_cont(false));
171
172 // Disable AWD interrupt
173 assert!(!T::regs().cr().read().adstart());
174 T::regs().ier().modify(|w| w.set_awdie(false));
175
176 // Clear AWD interrupt flag
177 while T::regs().isr().read().awd() {
178 T::regs().isr().modify(|regs| {
179 regs.set_awd(true);
180 })
181 }
182 }
183
184 pub(crate) fn teardown_awd() {
185 Self::stop_awd();
186 T::regs().cfgr1().modify(|w| w.set_awden(false));
187 }
188}
diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index 305666d5b..4c0795a2a 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -15,9 +15,10 @@ pub use embedded_can::{ExtendedId, Id, StandardId};
15use self::filter::MasterFilters; 15use self::filter::MasterFilters;
16use self::registers::{Registers, RxFifo}; 16use self::registers::{Registers, RxFifo};
17pub use super::common::{BufferedCanReceiver, BufferedCanSender}; 17pub use super::common::{BufferedCanReceiver, BufferedCanSender};
18use super::common::{InfoRef, RxInfoRef, TxInfoRef};
18use super::frame::{Envelope, Frame}; 19use super::frame::{Envelope, Frame};
19use super::util; 20use super::util;
20use crate::can::enums::{BusError, InternalOperation, TryReadError}; 21use crate::can::enums::{BusError, RefCountOp, TryReadError};
21use crate::gpio::{AfType, OutputType, Pull, Speed}; 22use crate::gpio::{AfType, OutputType, Pull, Speed};
22use crate::interrupt::typelevel::Interrupt; 23use crate::interrupt::typelevel::Interrupt;
23use crate::rcc::{self, RccPeripheral}; 24use crate::rcc::{self, RccPeripheral};
@@ -35,7 +36,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::TXInterrupt> for TxInterruptH
35 v.set_rqcp(1, true); 36 v.set_rqcp(1, true);
36 v.set_rqcp(2, true); 37 v.set_rqcp(2, true);
37 }); 38 });
38 T::state().tx_mode.on_interrupt::<T>(); 39 T::info().state.lock(|state| {
40 state.borrow().tx_mode.on_interrupt::<T>();
41 });
39 } 42 }
40} 43}
41 44
@@ -46,7 +49,9 @@ pub struct Rx0InterruptHandler<T: Instance> {
46 49
47impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> { 50impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
48 unsafe fn on_interrupt() { 51 unsafe fn on_interrupt() {
49 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo0); 52 T::info().state.lock(|state| {
53 state.borrow().rx_mode.on_interrupt::<T>(RxFifo::Fifo0);
54 });
50 } 55 }
51} 56}
52 57
@@ -57,7 +62,9 @@ pub struct Rx1InterruptHandler<T: Instance> {
57 62
58impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> { 63impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
59 unsafe fn on_interrupt() { 64 unsafe fn on_interrupt() {
60 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo1); 65 T::info().state.lock(|state| {
66 state.borrow().rx_mode.on_interrupt::<T>(RxFifo::Fifo1);
67 });
61 } 68 }
62} 69}
63 70
@@ -73,7 +80,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
73 80
74 if msr_val.slaki() { 81 if msr_val.slaki() {
75 msr.modify(|m| m.set_slaki(true)); 82 msr.modify(|m| m.set_slaki(true));
76 T::state().err_waker.wake(); 83 T::info().state.lock(|state| {
84 state.borrow().err_waker.wake();
85 });
77 } else if msr_val.erri() { 86 } else if msr_val.erri() {
78 // Disable the interrupt, but don't acknowledge the error, so that it can be 87 // Disable the interrupt, but don't acknowledge the error, so that it can be
79 // forwarded off the bus message consumer. If we don't provide some way for 88 // forwarded off the bus message consumer. If we don't provide some way for
@@ -82,8 +91,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
82 // an indefinite amount of time. 91 // an indefinite amount of time.
83 let ier = T::regs().ier(); 92 let ier = T::regs().ier();
84 ier.modify(|i| i.set_errie(false)); 93 ier.modify(|i| i.set_errie(false));
85 94 T::info().state.lock(|state| {
86 T::state().err_waker.wake(); 95 state.borrow().err_waker.wake();
96 });
87 } 97 }
88 } 98 }
89} 99}
@@ -91,7 +101,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
91/// Configuration proxy returned by [`Can::modify_config`]. 101/// Configuration proxy returned by [`Can::modify_config`].
92pub struct CanConfig<'a> { 102pub struct CanConfig<'a> {
93 phantom: PhantomData<&'a ()>, 103 phantom: PhantomData<&'a ()>,
94 info: &'static Info, 104 info: InfoRef,
95 periph_clock: crate::time::Hertz, 105 periph_clock: crate::time::Hertz,
96} 106}
97 107
@@ -156,8 +166,7 @@ impl Drop for CanConfig<'_> {
156/// CAN driver 166/// CAN driver
157pub struct Can<'d> { 167pub struct Can<'d> {
158 phantom: PhantomData<&'d ()>, 168 phantom: PhantomData<&'d ()>,
159 info: &'static Info, 169 info: InfoRef,
160 state: &'static State,
161 periph_clock: crate::time::Hertz, 170 periph_clock: crate::time::Hertz,
162} 171}
163 172
@@ -227,8 +236,7 @@ impl<'d> Can<'d> {
227 236
228 Self { 237 Self {
229 phantom: PhantomData, 238 phantom: PhantomData,
230 info: T::info(), 239 info: InfoRef::new(T::info()),
231 state: T::state(),
232 periph_clock: T::frequency(), 240 periph_clock: T::frequency(),
233 } 241 }
234 } 242 }
@@ -248,7 +256,7 @@ impl<'d> Can<'d> {
248 256
249 CanConfig { 257 CanConfig {
250 phantom: self.phantom, 258 phantom: self.phantom,
251 info: self.info, 259 info: InfoRef::new(&self.info),
252 periph_clock: self.periph_clock, 260 periph_clock: self.periph_clock,
253 } 261 }
254 } 262 }
@@ -297,7 +305,9 @@ impl<'d> Can<'d> {
297 self.info.regs.0.mcr().modify(|m| m.set_sleep(true)); 305 self.info.regs.0.mcr().modify(|m| m.set_sleep(true));
298 306
299 poll_fn(|cx| { 307 poll_fn(|cx| {
300 self.state.err_waker.register(cx.waker()); 308 self.info.state.lock(|s| {
309 s.borrow().err_waker.register(cx.waker());
310 });
301 if self.is_sleeping() { 311 if self.is_sleeping() {
302 Poll::Ready(()) 312 Poll::Ready(())
303 } else { 313 } else {
@@ -350,8 +360,7 @@ impl<'d> Can<'d> {
350 pub async fn flush(&self, mb: Mailbox) { 360 pub async fn flush(&self, mb: Mailbox) {
351 CanTx { 361 CanTx {
352 _phantom: PhantomData, 362 _phantom: PhantomData,
353 info: self.info, 363 info: TxInfoRef::new(&self.info),
354 state: self.state,
355 } 364 }
356 .flush_inner(mb) 365 .flush_inner(mb)
357 .await; 366 .await;
@@ -366,8 +375,7 @@ impl<'d> Can<'d> {
366 pub async fn flush_any(&self) { 375 pub async fn flush_any(&self) {
367 CanTx { 376 CanTx {
368 _phantom: PhantomData, 377 _phantom: PhantomData,
369 info: self.info, 378 info: TxInfoRef::new(&self.info),
370 state: self.state,
371 } 379 }
372 .flush_any_inner() 380 .flush_any_inner()
373 .await 381 .await
@@ -377,8 +385,7 @@ impl<'d> Can<'d> {
377 pub async fn flush_all(&self) { 385 pub async fn flush_all(&self) {
378 CanTx { 386 CanTx {
379 _phantom: PhantomData, 387 _phantom: PhantomData,
380 info: self.info, 388 info: TxInfoRef::new(&self.info),
381 state: self.state,
382 } 389 }
383 .flush_all_inner() 390 .flush_all_inner()
384 .await 391 .await
@@ -406,19 +413,19 @@ impl<'d> Can<'d> {
406 /// 413 ///
407 /// Returns a tuple of the time the message was received and the message frame 414 /// Returns a tuple of the time the message was received and the message frame
408 pub async fn read(&mut self) -> Result<Envelope, BusError> { 415 pub async fn read(&mut self) -> Result<Envelope, BusError> {
409 self.state.rx_mode.read(self.info, self.state).await 416 RxMode::read(&self.info).await
410 } 417 }
411 418
412 /// Attempts to read a CAN frame without blocking. 419 /// Attempts to read a CAN frame without blocking.
413 /// 420 ///
414 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 421 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
415 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 422 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
416 self.state.rx_mode.try_read(self.info) 423 RxMode::try_read(&self.info)
417 } 424 }
418 425
419 /// Waits while receive queue is empty. 426 /// Waits while receive queue is empty.
420 pub async fn wait_not_empty(&mut self) { 427 pub async fn wait_not_empty(&mut self) {
421 self.state.rx_mode.wait_not_empty(self.info, self.state).await 428 RxMode::wait_not_empty(&self.info).await
422 } 429 }
423 430
424 /// Split the CAN driver into transmit and receive halves. 431 /// Split the CAN driver into transmit and receive halves.
@@ -428,13 +435,11 @@ impl<'d> Can<'d> {
428 ( 435 (
429 CanTx { 436 CanTx {
430 _phantom: PhantomData, 437 _phantom: PhantomData,
431 info: self.info, 438 info: TxInfoRef::new(&self.info),
432 state: self.state,
433 }, 439 },
434 CanRx { 440 CanRx {
435 _phantom: PhantomData, 441 _phantom: PhantomData,
436 info: self.info, 442 info: RxInfoRef::new(&self.info),
437 state: self.state,
438 }, 443 },
439 ) 444 )
440 } 445 }
@@ -459,7 +464,7 @@ impl<'d> Can<'d> {
459 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master 464 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
460 /// peripheral instead. 465 /// peripheral instead.
461 pub fn modify_filters(&mut self) -> MasterFilters<'_> { 466 pub fn modify_filters(&mut self) -> MasterFilters<'_> {
462 unsafe { MasterFilters::new(self.info) } 467 unsafe { MasterFilters::new(&self.info) }
463 } 468 }
464} 469}
465 470
@@ -514,8 +519,7 @@ impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_
514/// CAN driver, transmit half. 519/// CAN driver, transmit half.
515pub struct CanTx<'d> { 520pub struct CanTx<'d> {
516 _phantom: PhantomData<&'d ()>, 521 _phantom: PhantomData<&'d ()>,
517 info: &'static Info, 522 info: TxInfoRef,
518 state: &'static State,
519} 523}
520 524
521impl<'d> CanTx<'d> { 525impl<'d> CanTx<'d> {
@@ -524,7 +528,9 @@ impl<'d> CanTx<'d> {
524 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. 528 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
525 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus { 529 pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
526 poll_fn(|cx| { 530 poll_fn(|cx| {
527 self.state.tx_mode.register(cx.waker()); 531 self.info.state.lock(|s| {
532 s.borrow().tx_mode.register(cx.waker());
533 });
528 if let Ok(status) = self.info.regs.transmit(frame) { 534 if let Ok(status) = self.info.regs.transmit(frame) {
529 return Poll::Ready(status); 535 return Poll::Ready(status);
530 } 536 }
@@ -549,7 +555,9 @@ impl<'d> CanTx<'d> {
549 555
550 async fn flush_inner(&self, mb: Mailbox) { 556 async fn flush_inner(&self, mb: Mailbox) {
551 poll_fn(|cx| { 557 poll_fn(|cx| {
552 self.state.tx_mode.register(cx.waker()); 558 self.info.state.lock(|s| {
559 s.borrow().tx_mode.register(cx.waker());
560 });
553 if self.info.regs.0.tsr().read().tme(mb.index()) { 561 if self.info.regs.0.tsr().read().tme(mb.index()) {
554 return Poll::Ready(()); 562 return Poll::Ready(());
555 } 563 }
@@ -566,7 +574,9 @@ impl<'d> CanTx<'d> {
566 574
567 async fn flush_any_inner(&self) { 575 async fn flush_any_inner(&self) {
568 poll_fn(|cx| { 576 poll_fn(|cx| {
569 self.state.tx_mode.register(cx.waker()); 577 self.info.state.lock(|s| {
578 s.borrow().tx_mode.register(cx.waker());
579 });
570 580
571 let tsr = self.info.regs.0.tsr().read(); 581 let tsr = self.info.regs.0.tsr().read();
572 if tsr.tme(Mailbox::Mailbox0.index()) 582 if tsr.tme(Mailbox::Mailbox0.index())
@@ -593,7 +603,9 @@ impl<'d> CanTx<'d> {
593 603
594 async fn flush_all_inner(&self) { 604 async fn flush_all_inner(&self) {
595 poll_fn(|cx| { 605 poll_fn(|cx| {
596 self.state.tx_mode.register(cx.waker()); 606 self.info.state.lock(|s| {
607 s.borrow().tx_mode.register(cx.waker());
608 });
597 609
598 let tsr = self.info.regs.0.tsr().read(); 610 let tsr = self.info.regs.0.tsr().read();
599 if tsr.tme(Mailbox::Mailbox0.index()) 611 if tsr.tme(Mailbox::Mailbox0.index())
@@ -634,7 +646,7 @@ impl<'d> CanTx<'d> {
634 self, 646 self,
635 txb: &'static mut TxBuf<TX_BUF_SIZE>, 647 txb: &'static mut TxBuf<TX_BUF_SIZE>,
636 ) -> BufferedCanTx<'d, TX_BUF_SIZE> { 648 ) -> BufferedCanTx<'d, TX_BUF_SIZE> {
637 BufferedCanTx::new(self.info, self.state, self, txb) 649 BufferedCanTx::new(&self.info, self, txb)
638 } 650 }
639} 651}
640 652
@@ -643,17 +655,15 @@ pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame,
643 655
644/// Buffered CAN driver, transmit half. 656/// Buffered CAN driver, transmit half.
645pub struct BufferedCanTx<'d, const TX_BUF_SIZE: usize> { 657pub struct BufferedCanTx<'d, const TX_BUF_SIZE: usize> {
646 info: &'static Info, 658 info: TxInfoRef,
647 state: &'static State,
648 _tx: CanTx<'d>, 659 _tx: CanTx<'d>,
649 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 660 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
650} 661}
651 662
652impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> { 663impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
653 fn new(info: &'static Info, state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self { 664 fn new(info: &'static Info, _tx: CanTx<'d>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
654 Self { 665 Self {
655 info, 666 info: TxInfoRef::new(info),
656 state,
657 _tx, 667 _tx,
658 tx_buf, 668 tx_buf,
659 } 669 }
@@ -666,11 +676,9 @@ impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
666 let tx_inner = super::common::ClassicBufferedTxInner { 676 let tx_inner = super::common::ClassicBufferedTxInner {
667 tx_receiver: self.tx_buf.receiver().into(), 677 tx_receiver: self.tx_buf.receiver().into(),
668 }; 678 };
669 let state = self.state as *const State; 679 self.info.state.lock(|s| {
670 unsafe { 680 s.borrow_mut().tx_mode = TxMode::Buffered(tx_inner);
671 let mut_state = state as *mut State; 681 });
672 (*mut_state).tx_mode = TxMode::Buffered(tx_inner);
673 }
674 }); 682 });
675 self 683 self
676 } 684 }
@@ -684,27 +692,18 @@ impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
684 692
685 /// Returns a sender that can be used for sending CAN frames. 693 /// Returns a sender that can be used for sending CAN frames.
686 pub fn writer(&self) -> BufferedCanSender { 694 pub fn writer(&self) -> BufferedCanSender {
687 (self.info.internal_operation)(InternalOperation::NotifySenderCreated);
688 BufferedCanSender { 695 BufferedCanSender {
689 tx_buf: self.tx_buf.sender().into(), 696 tx_buf: self.tx_buf.sender().into(),
690 waker: self.info.tx_waker, 697 info: TxInfoRef::new(&self.info),
691 internal_operation: self.info.internal_operation,
692 } 698 }
693 } 699 }
694} 700}
695 701
696impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> {
697 fn drop(&mut self) {
698 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
699 }
700}
701
702/// CAN driver, receive half. 702/// CAN driver, receive half.
703#[allow(dead_code)] 703#[allow(dead_code)]
704pub struct CanRx<'d> { 704pub struct CanRx<'d> {
705 _phantom: PhantomData<&'d ()>, 705 _phantom: PhantomData<&'d ()>,
706 info: &'static Info, 706 info: RxInfoRef,
707 state: &'static State,
708} 707}
709 708
710impl<'d> CanRx<'d> { 709impl<'d> CanRx<'d> {
@@ -714,19 +713,19 @@ impl<'d> CanRx<'d> {
714 /// 713 ///
715 /// Returns a tuple of the time the message was received and the message frame 714 /// Returns a tuple of the time the message was received and the message frame
716 pub async fn read(&mut self) -> Result<Envelope, BusError> { 715 pub async fn read(&mut self) -> Result<Envelope, BusError> {
717 self.state.rx_mode.read(self.info, self.state).await 716 RxMode::read(&self.info).await
718 } 717 }
719 718
720 /// Attempts to read a CAN frame without blocking. 719 /// Attempts to read a CAN frame without blocking.
721 /// 720 ///
722 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 721 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
723 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 722 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
724 self.state.rx_mode.try_read(self.info) 723 RxMode::try_read(&self.info)
725 } 724 }
726 725
727 /// Waits while receive queue is empty. 726 /// Waits while receive queue is empty.
728 pub async fn wait_not_empty(&mut self) { 727 pub async fn wait_not_empty(&mut self) {
729 self.state.rx_mode.wait_not_empty(self.info, self.state).await 728 RxMode::wait_not_empty(&self.info).await
730 } 729 }
731 730
732 /// Return a buffered instance of driver. User must supply Buffers 731 /// Return a buffered instance of driver. User must supply Buffers
@@ -734,7 +733,7 @@ impl<'d> CanRx<'d> {
734 self, 733 self,
735 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 734 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
736 ) -> BufferedCanRx<'d, RX_BUF_SIZE> { 735 ) -> BufferedCanRx<'d, RX_BUF_SIZE> {
737 BufferedCanRx::new(self.info, self.state, self, rxb) 736 BufferedCanRx::new(&self.info, self, rxb)
738 } 737 }
739 738
740 /// Accesses the filter banks owned by this CAN peripheral. 739 /// Accesses the filter banks owned by this CAN peripheral.
@@ -742,7 +741,7 @@ impl<'d> CanRx<'d> {
742 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master 741 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
743 /// peripheral instead. 742 /// peripheral instead.
744 pub fn modify_filters(&mut self) -> MasterFilters<'_> { 743 pub fn modify_filters(&mut self) -> MasterFilters<'_> {
745 unsafe { MasterFilters::new(self.info) } 744 unsafe { MasterFilters::new(&self.info) }
746 } 745 }
747} 746}
748 747
@@ -751,17 +750,15 @@ pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<
751 750
752/// CAN driver, receive half in Buffered mode. 751/// CAN driver, receive half in Buffered mode.
753pub struct BufferedCanRx<'d, const RX_BUF_SIZE: usize> { 752pub struct BufferedCanRx<'d, const RX_BUF_SIZE: usize> {
754 info: &'static Info, 753 info: RxInfoRef,
755 state: &'static State,
756 rx: CanRx<'d>, 754 rx: CanRx<'d>,
757 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 755 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
758} 756}
759 757
760impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { 758impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
761 fn new(info: &'static Info, state: &'static State, rx: CanRx<'d>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self { 759 fn new(info: &'static Info, rx: CanRx<'d>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
762 BufferedCanRx { 760 BufferedCanRx {
763 info, 761 info: RxInfoRef::new(info),
764 state,
765 rx, 762 rx,
766 rx_buf, 763 rx_buf,
767 } 764 }
@@ -774,11 +771,9 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
774 let rx_inner = super::common::ClassicBufferedRxInner { 771 let rx_inner = super::common::ClassicBufferedRxInner {
775 rx_sender: self.rx_buf.sender().into(), 772 rx_sender: self.rx_buf.sender().into(),
776 }; 773 };
777 let state = self.state as *const State; 774 self.info.state.lock(|s| {
778 unsafe { 775 s.borrow_mut().rx_mode = RxMode::Buffered(rx_inner);
779 let mut_state = state as *mut State; 776 });
780 (*mut_state).rx_mode = RxMode::Buffered(rx_inner);
781 }
782 }); 777 });
783 self 778 self
784 } 779 }
@@ -792,7 +787,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
792 /// 787 ///
793 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 788 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
794 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 789 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
795 match &self.state.rx_mode { 790 self.info.state.lock(|s| match &s.borrow().rx_mode {
796 RxMode::Buffered(_) => { 791 RxMode::Buffered(_) => {
797 if let Ok(result) = self.rx_buf.try_receive() { 792 if let Ok(result) = self.rx_buf.try_receive() {
798 match result { 793 match result {
@@ -810,7 +805,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
810 _ => { 805 _ => {
811 panic!("Bad Mode") 806 panic!("Bad Mode")
812 } 807 }
813 } 808 })
814 } 809 }
815 810
816 /// Waits while receive queue is empty. 811 /// Waits while receive queue is empty.
@@ -820,10 +815,9 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
820 815
821 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. 816 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
822 pub fn reader(&self) -> BufferedCanReceiver { 817 pub fn reader(&self) -> BufferedCanReceiver {
823 (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
824 BufferedCanReceiver { 818 BufferedCanReceiver {
825 rx_buf: self.rx_buf.receiver().into(), 819 rx_buf: self.rx_buf.receiver().into(),
826 internal_operation: self.info.internal_operation, 820 info: RxInfoRef::new(&self.info),
827 } 821 }
828 } 822 }
829 823
@@ -836,12 +830,6 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
836 } 830 }
837} 831}
838 832
839impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> {
840 fn drop(&mut self) {
841 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
842 }
843}
844
845impl Drop for Can<'_> { 833impl Drop for Can<'_> {
846 fn drop(&mut self) { 834 fn drop(&mut self) {
847 // Cannot call `free()` because it moves the instance. 835 // Cannot call `free()` because it moves the instance.
@@ -929,27 +917,30 @@ impl RxMode {
929 } 917 }
930 } 918 }
931 919
932 pub(crate) async fn read(&self, info: &Info, state: &State) -> Result<Envelope, BusError> { 920 pub(crate) async fn read(info: &Info) -> Result<Envelope, BusError> {
933 match self { 921 poll_fn(|cx| {
934 Self::NonBuffered(waker) => { 922 info.state.lock(|state| {
935 poll_fn(|cx| { 923 let state = state.borrow();
936 state.err_waker.register(cx.waker()); 924 state.err_waker.register(cx.waker());
937 waker.register(cx.waker()); 925 match &state.rx_mode {
938 match self.try_read(info) { 926 Self::NonBuffered(waker) => {
939 Ok(result) => Poll::Ready(Ok(result)), 927 waker.register(cx.waker());
940 Err(TryReadError::Empty) => Poll::Pending,
941 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
942 } 928 }
943 }) 929 _ => {
944 .await 930 panic!("Bad Mode")
945 } 931 }
946 _ => { 932 }
947 panic!("Bad Mode") 933 });
934 match RxMode::try_read(info) {
935 Ok(result) => Poll::Ready(Ok(result)),
936 Err(TryReadError::Empty) => Poll::Pending,
937 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
948 } 938 }
949 } 939 })
940 .await
950 } 941 }
951 pub(crate) fn try_read(&self, info: &Info) -> Result<Envelope, TryReadError> { 942 pub(crate) fn try_read(info: &Info) -> Result<Envelope, TryReadError> {
952 match self { 943 info.state.lock(|state| match state.borrow().rx_mode {
953 Self::NonBuffered(_) => { 944 Self::NonBuffered(_) => {
954 let registers = &info.regs; 945 let registers = &info.regs;
955 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) { 946 if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
@@ -975,25 +966,28 @@ impl RxMode {
975 _ => { 966 _ => {
976 panic!("Bad Mode") 967 panic!("Bad Mode")
977 } 968 }
978 } 969 })
979 } 970 }
980 pub(crate) async fn wait_not_empty(&self, info: &Info, state: &State) { 971 pub(crate) async fn wait_not_empty(info: &Info) {
981 match &state.rx_mode { 972 poll_fn(|cx| {
982 Self::NonBuffered(waker) => { 973 info.state.lock(|s| {
983 poll_fn(|cx| { 974 let state = s.borrow();
984 waker.register(cx.waker()); 975 match &state.rx_mode {
985 if info.regs.receive_frame_available() { 976 Self::NonBuffered(waker) => {
986 Poll::Ready(()) 977 waker.register(cx.waker());
987 } else {
988 Poll::Pending
989 } 978 }
990 }) 979 _ => {
991 .await 980 panic!("Bad Mode")
992 } 981 }
993 _ => { 982 }
994 panic!("Bad Mode") 983 });
984 if info.regs.receive_frame_available() {
985 Poll::Ready(())
986 } else {
987 Poll::Pending
995 } 988 }
996 } 989 })
990 .await
997 } 991 }
998} 992}
999 993
@@ -1008,21 +1002,25 @@ impl TxMode {
1008 tsr.tme(Mailbox::Mailbox0.index()) || tsr.tme(Mailbox::Mailbox1.index()) || tsr.tme(Mailbox::Mailbox2.index()) 1002 tsr.tme(Mailbox::Mailbox0.index()) || tsr.tme(Mailbox::Mailbox1.index()) || tsr.tme(Mailbox::Mailbox2.index())
1009 } 1003 }
1010 pub fn on_interrupt<T: Instance>(&self) { 1004 pub fn on_interrupt<T: Instance>(&self) {
1011 match &T::state().tx_mode { 1005 T::info().state.lock(|state| {
1012 TxMode::NonBuffered(waker) => waker.wake(), 1006 let tx_mode = &state.borrow().tx_mode;
1013 TxMode::Buffered(buf) => { 1007
1014 while self.buffer_free::<T>() { 1008 match tx_mode {
1015 match buf.tx_receiver.try_receive() { 1009 TxMode::NonBuffered(waker) => waker.wake(),
1016 Ok(frame) => { 1010 TxMode::Buffered(buf) => {
1017 _ = Registers(T::regs()).transmit(&frame); 1011 while self.buffer_free::<T>() {
1018 } 1012 match buf.tx_receiver.try_receive() {
1019 Err(_) => { 1013 Ok(frame) => {
1020 break; 1014 _ = Registers(T::regs()).transmit(&frame);
1015 }
1016 Err(_) => {
1017 break;
1018 }
1021 } 1019 }
1022 } 1020 }
1023 } 1021 }
1024 } 1022 }
1025 } 1023 });
1026 } 1024 }
1027 1025
1028 fn register(&self, arg: &core::task::Waker) { 1026 fn register(&self, arg: &core::task::Waker) {
@@ -1057,14 +1055,15 @@ impl State {
1057 } 1055 }
1058} 1056}
1059 1057
1058type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<State>>;
1060pub(crate) struct Info { 1059pub(crate) struct Info {
1061 regs: Registers, 1060 regs: Registers,
1062 tx_interrupt: crate::interrupt::Interrupt, 1061 tx_interrupt: crate::interrupt::Interrupt,
1063 rx0_interrupt: crate::interrupt::Interrupt, 1062 rx0_interrupt: crate::interrupt::Interrupt,
1064 rx1_interrupt: crate::interrupt::Interrupt, 1063 rx1_interrupt: crate::interrupt::Interrupt,
1065 sce_interrupt: crate::interrupt::Interrupt, 1064 sce_interrupt: crate::interrupt::Interrupt,
1066 tx_waker: fn(), 1065 pub(crate) tx_waker: fn(),
1067 internal_operation: fn(InternalOperation), 1066 state: SharedState,
1068 1067
1069 /// The total number of filter banks available to the instance. 1068 /// The total number of filter banks available to the instance.
1070 /// 1069 ///
@@ -1072,12 +1071,37 @@ pub(crate) struct Info {
1072 num_filter_banks: u8, 1071 num_filter_banks: u8,
1073} 1072}
1074 1073
1074impl Info {
1075 pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) {
1076 self.state.lock(|s| {
1077 let mut mut_state = s.borrow_mut();
1078 match val {
1079 RefCountOp::NotifySenderCreated => {
1080 mut_state.sender_instance_count += 1;
1081 }
1082 RefCountOp::NotifySenderDestroyed => {
1083 mut_state.sender_instance_count -= 1;
1084 if 0 == mut_state.sender_instance_count {
1085 (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
1086 }
1087 }
1088 RefCountOp::NotifyReceiverCreated => {
1089 mut_state.receiver_instance_count += 1;
1090 }
1091 RefCountOp::NotifyReceiverDestroyed => {
1092 mut_state.receiver_instance_count -= 1;
1093 if 0 == mut_state.receiver_instance_count {
1094 (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
1095 }
1096 }
1097 }
1098 });
1099 }
1100}
1101
1075trait SealedInstance { 1102trait SealedInstance {
1076 fn info() -> &'static Info; 1103 fn info() -> &'static Info;
1077 fn regs() -> crate::pac::can::Can; 1104 fn regs() -> crate::pac::can::Can;
1078 fn state() -> &'static State;
1079 unsafe fn mut_state() -> &'static mut State;
1080 fn internal_operation(val: InternalOperation);
1081} 1105}
1082 1106
1083/// CAN instance trait. 1107/// CAN instance trait.
@@ -1135,53 +1159,14 @@ foreach_peripheral!(
1135 rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ, 1159 rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
1136 sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, 1160 sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
1137 tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, 1161 tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
1138 internal_operation: peripherals::$inst::internal_operation,
1139 num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, 1162 num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS,
1163 state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())),
1140 }; 1164 };
1141 &INFO 1165 &INFO
1142 } 1166 }
1143 fn regs() -> crate::pac::can::Can { 1167 fn regs() -> crate::pac::can::Can {
1144 crate::pac::$inst 1168 crate::pac::$inst
1145 } 1169 }
1146
1147 unsafe fn mut_state() -> & 'static mut State {
1148 static mut STATE: State = State::new();
1149 &mut *core::ptr::addr_of_mut!(STATE)
1150 }
1151 fn state() -> &'static State {
1152 unsafe { peripherals::$inst::mut_state() }
1153 }
1154
1155
1156 fn internal_operation(val: InternalOperation) {
1157 critical_section::with(|_| {
1158 //let state = self.state as *const State;
1159 unsafe {
1160 //let mut_state = state as *mut State;
1161 let mut_state = peripherals::$inst::mut_state();
1162 match val {
1163 InternalOperation::NotifySenderCreated => {
1164 mut_state.sender_instance_count += 1;
1165 }
1166 InternalOperation::NotifySenderDestroyed => {
1167 mut_state.sender_instance_count -= 1;
1168 if ( 0 == mut_state.sender_instance_count) {
1169 (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
1170 }
1171 }
1172 InternalOperation::NotifyReceiverCreated => {
1173 mut_state.receiver_instance_count += 1;
1174 }
1175 InternalOperation::NotifyReceiverDestroyed => {
1176 mut_state.receiver_instance_count -= 1;
1177 if ( 0 == mut_state.receiver_instance_count) {
1178 (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
1179 }
1180 }
1181 }
1182 }
1183 });
1184 }
1185 } 1170 }
1186 1171
1187 impl Instance for peripherals::$inst { 1172 impl Instance for peripherals::$inst {
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs
index 386d4467c..980f33a04 100644
--- a/embassy-stm32/src/can/common.rs
+++ b/embassy-stm32/src/can/common.rs
@@ -24,22 +24,21 @@ pub(crate) struct FdBufferedTxInner {
24/// Sender that can be used for sending CAN frames. 24/// Sender that can be used for sending CAN frames.
25pub struct BufferedSender<'ch, FRAME> { 25pub struct BufferedSender<'ch, FRAME> {
26 pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>, 26 pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>,
27 pub(crate) waker: fn(), 27 pub(crate) info: TxInfoRef,
28 pub(crate) internal_operation: fn(InternalOperation),
29} 28}
30 29
31impl<'ch, FRAME> BufferedSender<'ch, FRAME> { 30impl<'ch, FRAME> BufferedSender<'ch, FRAME> {
32 /// Async write frame to TX buffer. 31 /// Async write frame to TX buffer.
33 pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError<FRAME>> { 32 pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError<FRAME>> {
34 self.tx_buf.try_send(frame)?; 33 self.tx_buf.try_send(frame)?;
35 (self.waker)(); 34 (self.info.tx_waker)();
36 Ok(()) 35 Ok(())
37 } 36 }
38 37
39 /// Async write frame to TX buffer. 38 /// Async write frame to TX buffer.
40 pub async fn write(&mut self, frame: FRAME) { 39 pub async fn write(&mut self, frame: FRAME) {
41 self.tx_buf.send(frame).await; 40 self.tx_buf.send(frame).await;
42 (self.waker)(); 41 (self.info.tx_waker)();
43 } 42 }
44 43
45 /// Allows a poll_fn to poll until the channel is ready to write 44 /// Allows a poll_fn to poll until the channel is ready to write
@@ -50,28 +49,20 @@ impl<'ch, FRAME> BufferedSender<'ch, FRAME> {
50 49
51impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> { 50impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> {
52 fn clone(&self) -> Self { 51 fn clone(&self) -> Self {
53 (self.internal_operation)(InternalOperation::NotifySenderCreated);
54 Self { 52 Self {
55 tx_buf: self.tx_buf, 53 tx_buf: self.tx_buf,
56 waker: self.waker, 54 info: TxInfoRef::new(&self.info),
57 internal_operation: self.internal_operation,
58 } 55 }
59 } 56 }
60} 57}
61 58
62impl<'ch, FRAME> Drop for BufferedSender<'ch, FRAME> {
63 fn drop(&mut self) {
64 (self.internal_operation)(InternalOperation::NotifySenderDestroyed);
65 }
66}
67
68/// Sender that can be used for sending Classic CAN frames. 59/// Sender that can be used for sending Classic CAN frames.
69pub type BufferedCanSender = BufferedSender<'static, Frame>; 60pub type BufferedCanSender = BufferedSender<'static, Frame>;
70 61
71/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. 62/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
72pub struct BufferedReceiver<'ch, ENVELOPE> { 63pub struct BufferedReceiver<'ch, ENVELOPE> {
73 pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result<ENVELOPE, BusError>>, 64 pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result<ENVELOPE, BusError>>,
74 pub(crate) internal_operation: fn(InternalOperation), 65 pub(crate) info: RxInfoRef,
75} 66}
76 67
77impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> { 68impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> {
@@ -106,19 +97,99 @@ impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> {
106 97
107impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> { 98impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> {
108 fn clone(&self) -> Self { 99 fn clone(&self) -> Self {
109 (self.internal_operation)(InternalOperation::NotifyReceiverCreated);
110 Self { 100 Self {
111 rx_buf: self.rx_buf, 101 rx_buf: self.rx_buf,
112 internal_operation: self.internal_operation, 102 info: RxInfoRef::new(&self.info),
113 } 103 }
114 } 104 }
115} 105}
116 106
117impl<'ch, ENVELOPE> Drop for BufferedReceiver<'ch, ENVELOPE> { 107/// A BufferedCanReceiver for Classic CAN frames.
108pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>;
109
110/// Provides a reference to the driver internals and implements RAII for the internal reference
111/// counting. Each type that can operate on the driver should contain either InfoRef
112/// or the similar TxInfoRef or RxInfoRef. The new method and the Drop impl will automatically
113/// call the reference counting function. Like this, the reference counting function does not
114/// need to be called manually for each type.
115pub(crate) struct InfoRef {
116 info: &'static super::Info,
117}
118impl InfoRef {
119 pub(crate) fn new(info: &'static super::Info) -> Self {
120 info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated);
121 info.adjust_reference_counter(RefCountOp::NotifySenderCreated);
122 Self { info }
123 }
124}
125
126impl Drop for InfoRef {
118 fn drop(&mut self) { 127 fn drop(&mut self) {
119 (self.internal_operation)(InternalOperation::NotifyReceiverDestroyed); 128 self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed);
129 self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed);
120 } 130 }
121} 131}
122 132
123/// A BufferedCanReceiver for Classic CAN frames. 133impl core::ops::Deref for InfoRef {
124pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>; 134 type Target = &'static super::Info;
135
136 fn deref(&self) -> &Self::Target {
137 &self.info
138 }
139}
140
141/// Provides a reference to the driver internals and implements RAII for the internal reference
142/// counting for Tx only types.
143/// See InfoRef for further doc.
144pub(crate) struct TxInfoRef {
145 info: &'static super::Info,
146}
147
148impl TxInfoRef {
149 pub(crate) fn new(info: &'static super::Info) -> Self {
150 info.adjust_reference_counter(RefCountOp::NotifySenderCreated);
151 Self { info }
152 }
153}
154
155impl Drop for TxInfoRef {
156 fn drop(&mut self) {
157 self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed);
158 }
159}
160
161impl core::ops::Deref for TxInfoRef {
162 type Target = &'static super::Info;
163
164 fn deref(&self) -> &Self::Target {
165 &self.info
166 }
167}
168
169/// Provides a reference to the driver internals and implements RAII for the internal reference
170/// counting for Rx only types.
171/// See InfoRef for further doc.
172pub(crate) struct RxInfoRef {
173 info: &'static super::Info,
174}
175
176impl RxInfoRef {
177 pub(crate) fn new(info: &'static super::Info) -> Self {
178 info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated);
179 Self { info }
180 }
181}
182
183impl Drop for RxInfoRef {
184 fn drop(&mut self) {
185 self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed);
186 }
187}
188
189impl core::ops::Deref for RxInfoRef {
190 type Target = &'static super::Info;
191
192 fn deref(&self) -> &Self::Target {
193 &self.info
194 }
195}
diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs
index 97cb47640..6d91020fc 100644
--- a/embassy-stm32/src/can/enums.rs
+++ b/embassy-stm32/src/can/enums.rs
@@ -72,7 +72,7 @@ pub enum TryReadError {
72/// Internal Operation 72/// Internal Operation
73#[derive(Debug)] 73#[derive(Debug)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75pub enum InternalOperation { 75pub enum RefCountOp {
76 /// Notify receiver created 76 /// Notify receiver created
77 NotifyReceiverCreated, 77 NotifyReceiverCreated,
78 /// Notify receiver destroyed 78 /// Notify receiver destroyed
diff --git a/embassy-stm32/src/can/fd/message_ram/extended_filter.rs b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs
index 453e9056e..ac47901a8 100644
--- a/embassy-stm32/src/can/fd/message_ram/extended_filter.rs
+++ b/embassy-stm32/src/can/fd/message_ram/extended_filter.rs
@@ -115,22 +115,22 @@ impl R {
115impl W { 115impl W {
116 #[doc = "Byte 0 - Bits 0:28 - EFID1"] 116 #[doc = "Byte 0 - Bits 0:28 - EFID1"]
117 #[inline(always)] 117 #[inline(always)]
118 pub fn efid1(&mut self) -> EFID1_W { 118 pub fn efid1(&mut self) -> EFID1_W<'_> {
119 EFID1_W { w: self } 119 EFID1_W { w: self }
120 } 120 }
121 #[doc = "Byte 0 - Bits 29:31 - EFEC"] 121 #[doc = "Byte 0 - Bits 29:31 - EFEC"]
122 #[inline(always)] 122 #[inline(always)]
123 pub fn efec(&mut self) -> EFEC_W { 123 pub fn efec(&mut self) -> EFEC_W<'_> {
124 EFEC_W { w: self } 124 EFEC_W { w: self }
125 } 125 }
126 #[doc = "Byte 1 - Bits 0:28 - EFID2"] 126 #[doc = "Byte 1 - Bits 0:28 - EFID2"]
127 #[inline(always)] 127 #[inline(always)]
128 pub fn efid2(&mut self) -> EFID2_W { 128 pub fn efid2(&mut self) -> EFID2_W<'_> {
129 EFID2_W { w: self } 129 EFID2_W { w: self }
130 } 130 }
131 #[doc = "Byte 1 - Bits 30:31 - EFT"] 131 #[doc = "Byte 1 - Bits 30:31 - EFT"]
132 #[inline(always)] 132 #[inline(always)]
133 pub fn eft(&mut self) -> EFT_W { 133 pub fn eft(&mut self) -> EFT_W<'_> {
134 EFT_W { w: self } 134 EFT_W { w: self }
135 } 135 }
136} 136}
diff --git a/embassy-stm32/src/can/fd/message_ram/standard_filter.rs b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs
index 3a3bbcf12..f52646bfe 100644
--- a/embassy-stm32/src/can/fd/message_ram/standard_filter.rs
+++ b/embassy-stm32/src/can/fd/message_ram/standard_filter.rs
@@ -115,22 +115,22 @@ impl R {
115impl W { 115impl W {
116 #[doc = "Bits 0:10 - SFID2"] 116 #[doc = "Bits 0:10 - SFID2"]
117 #[inline(always)] 117 #[inline(always)]
118 pub fn sfid2(&mut self) -> SFID2_W { 118 pub fn sfid2(&mut self) -> SFID2_W<'_> {
119 SFID2_W { w: self } 119 SFID2_W { w: self }
120 } 120 }
121 #[doc = "Bits 16:26 - SFID1"] 121 #[doc = "Bits 16:26 - SFID1"]
122 #[inline(always)] 122 #[inline(always)]
123 pub fn sfid1(&mut self) -> SFID1_W { 123 pub fn sfid1(&mut self) -> SFID1_W<'_> {
124 SFID1_W { w: self } 124 SFID1_W { w: self }
125 } 125 }
126 #[doc = "Bits 27:29 - SFEC"] 126 #[doc = "Bits 27:29 - SFEC"]
127 #[inline(always)] 127 #[inline(always)]
128 pub fn sfec(&mut self) -> SFEC_W { 128 pub fn sfec(&mut self) -> SFEC_W<'_> {
129 SFEC_W { w: self } 129 SFEC_W { w: self }
130 } 130 }
131 #[doc = "Bits 30:31 - SFT"] 131 #[doc = "Bits 30:31 - SFT"]
132 #[inline(always)] 132 #[inline(always)]
133 pub fn sft(&mut self) -> SFT_W { 133 pub fn sft(&mut self) -> SFT_W<'_> {
134 SFT_W { w: self } 134 SFT_W { w: self }
135 } 135 }
136} 136}
diff --git a/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs
index 455406a1c..6d65a86cb 100644
--- a/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs
+++ b/embassy-stm32/src/can/fd/message_ram/txbuffer_element.rs
@@ -376,47 +376,47 @@ impl R {
376impl W { 376impl W {
377 #[doc = "Byte 0 - Bits 0:28 - ID"] 377 #[doc = "Byte 0 - Bits 0:28 - ID"]
378 #[inline(always)] 378 #[inline(always)]
379 pub fn id(&mut self) -> ID_W { 379 pub fn id(&mut self) -> ID_W<'_> {
380 ID_W { w: self } 380 ID_W { w: self }
381 } 381 }
382 #[doc = "Byte 0 - Bit 29 - RTR"] 382 #[doc = "Byte 0 - Bit 29 - RTR"]
383 #[inline(always)] 383 #[inline(always)]
384 pub fn rtr(&mut self) -> RTR_W { 384 pub fn rtr(&mut self) -> RTR_W<'_> {
385 RTR_W { w: self } 385 RTR_W { w: self }
386 } 386 }
387 #[doc = "Byte 0 - Bit 30 - XTD"] 387 #[doc = "Byte 0 - Bit 30 - XTD"]
388 #[inline(always)] 388 #[inline(always)]
389 pub fn xtd(&mut self) -> XTD_W { 389 pub fn xtd(&mut self) -> XTD_W<'_> {
390 XTD_W { w: self } 390 XTD_W { w: self }
391 } 391 }
392 #[doc = "Byte 0 - Bit 31 - ESI"] 392 #[doc = "Byte 0 - Bit 31 - ESI"]
393 #[inline(always)] 393 #[inline(always)]
394 pub fn esi(&mut self) -> ESI_W { 394 pub fn esi(&mut self) -> ESI_W<'_> {
395 ESI_W { w: self } 395 ESI_W { w: self }
396 } 396 }
397 #[doc = "Byte 1 - Bit 16:19 - DLC"] 397 #[doc = "Byte 1 - Bit 16:19 - DLC"]
398 #[inline(always)] 398 #[inline(always)]
399 pub fn dlc(&mut self) -> DLC_W { 399 pub fn dlc(&mut self) -> DLC_W<'_> {
400 DLC_W { w: self } 400 DLC_W { w: self }
401 } 401 }
402 #[doc = "Byte 1 - Bit 20 - BRS"] 402 #[doc = "Byte 1 - Bit 20 - BRS"]
403 #[inline(always)] 403 #[inline(always)]
404 pub fn brs(&mut self) -> BRS_W { 404 pub fn brs(&mut self) -> BRS_W<'_> {
405 BRS_W { w: self } 405 BRS_W { w: self }
406 } 406 }
407 #[doc = "Byte 1 - Bit 21 - FDF"] 407 #[doc = "Byte 1 - Bit 21 - FDF"]
408 #[inline(always)] 408 #[inline(always)]
409 pub fn fdf(&mut self) -> FDF_W { 409 pub fn fdf(&mut self) -> FDF_W<'_> {
410 FDF_W { w: self } 410 FDF_W { w: self }
411 } 411 }
412 #[doc = "Byte 1 - Bit 23 - EFC"] 412 #[doc = "Byte 1 - Bit 23 - EFC"]
413 #[inline(always)] 413 #[inline(always)]
414 pub fn efc(&mut self) -> EFC_W { 414 pub fn efc(&mut self) -> EFC_W<'_> {
415 EFC_W { w: self } 415 EFC_W { w: self }
416 } 416 }
417 #[doc = "Byte 1 - Bit 24:31 - MM"] 417 #[doc = "Byte 1 - Bit 24:31 - MM"]
418 #[inline(always)] 418 #[inline(always)]
419 pub fn mm(&mut self) -> MM_W { 419 pub fn mm(&mut self) -> MM_W<'_> {
420 MM_W { w: self } 420 MM_W { w: self }
421 } 421 }
422 #[doc = "Convenience function for setting the data length and frame format"] 422 #[doc = "Convenience function for setting the data length and frame format"]
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 97d22315a..99e40ba62 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -21,6 +21,7 @@ use self::fd::config::*;
21use self::fd::filter::*; 21use self::fd::filter::*;
22pub use self::fd::{config, filter}; 22pub use self::fd::{config, filter};
23pub use super::common::{BufferedCanReceiver, BufferedCanSender}; 23pub use super::common::{BufferedCanReceiver, BufferedCanSender};
24use super::common::{InfoRef, RxInfoRef, TxInfoRef};
24use super::enums::*; 25use super::enums::*;
25use super::frame::*; 26use super::frame::*;
26use super::util; 27use super::util;
@@ -167,10 +168,10 @@ fn calc_ns_per_timer_tick(
167pub struct CanConfigurator<'d> { 168pub struct CanConfigurator<'d> {
168 _phantom: PhantomData<&'d ()>, 169 _phantom: PhantomData<&'d ()>,
169 config: crate::can::fd::config::FdCanConfig, 170 config: crate::can::fd::config::FdCanConfig,
170 info: &'static Info,
171 /// Reference to internals. 171 /// Reference to internals.
172 properties: Properties, 172 properties: Properties,
173 periph_clock: crate::time::Hertz, 173 periph_clock: crate::time::Hertz,
174 info: InfoRef,
174} 175}
175 176
176impl<'d> CanConfigurator<'d> { 177impl<'d> CanConfigurator<'d> {
@@ -194,8 +195,6 @@ impl<'d> CanConfigurator<'d> {
194 s.borrow_mut().tx_pin_port = Some(tx.pin_port()); 195 s.borrow_mut().tx_pin_port = Some(tx.pin_port());
195 s.borrow_mut().rx_pin_port = Some(rx.pin_port()); 196 s.borrow_mut().rx_pin_port = Some(rx.pin_port());
196 }); 197 });
197 (info.internal_operation)(InternalOperation::NotifySenderCreated);
198 (info.internal_operation)(InternalOperation::NotifyReceiverCreated);
199 198
200 let mut config = crate::can::fd::config::FdCanConfig::default(); 199 let mut config = crate::can::fd::config::FdCanConfig::default();
201 config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1); 200 config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1);
@@ -211,9 +210,9 @@ impl<'d> CanConfigurator<'d> {
211 Self { 210 Self {
212 _phantom: PhantomData, 211 _phantom: PhantomData,
213 config, 212 config,
214 info,
215 properties: Properties::new(T::info()), 213 properties: Properties::new(T::info()),
216 periph_clock: T::frequency(), 214 periph_clock: T::frequency(),
215 info: InfoRef::new(info),
217 } 216 }
218 } 217 }
219 218
@@ -262,19 +261,17 @@ impl<'d> CanConfigurator<'d> {
262 261
263 /// Start in mode. 262 /// Start in mode.
264 pub fn start(self, mode: OperatingMode) -> Can<'d> { 263 pub fn start(self, mode: OperatingMode) -> Can<'d> {
265 let ns_per_timer_tick = calc_ns_per_timer_tick(self.info, self.periph_clock, self.config.frame_transmit); 264 let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit);
266 self.info.state.lock(|s| { 265 self.info.state.lock(|s| {
267 s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick; 266 s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick;
268 }); 267 });
269 self.info.regs.into_mode(self.config, mode); 268 self.info.regs.into_mode(self.config, mode);
270 (self.info.internal_operation)(InternalOperation::NotifySenderCreated);
271 (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
272 Can { 269 Can {
273 _phantom: PhantomData, 270 _phantom: PhantomData,
274 config: self.config, 271 config: self.config,
275 info: self.info,
276 _mode: mode, 272 _mode: mode,
277 properties: Properties::new(self.info), 273 properties: Properties::new(&self.info),
274 info: InfoRef::new(&self.info),
278 } 275 }
279 } 276 }
280 277
@@ -294,20 +291,13 @@ impl<'d> CanConfigurator<'d> {
294 } 291 }
295} 292}
296 293
297impl<'d> Drop for CanConfigurator<'d> {
298 fn drop(&mut self) {
299 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
300 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
301 }
302}
303
304/// FDCAN Instance 294/// FDCAN Instance
305pub struct Can<'d> { 295pub struct Can<'d> {
306 _phantom: PhantomData<&'d ()>, 296 _phantom: PhantomData<&'d ()>,
307 config: crate::can::fd::config::FdCanConfig, 297 config: crate::can::fd::config::FdCanConfig,
308 info: &'static Info,
309 _mode: OperatingMode, 298 _mode: OperatingMode,
310 properties: Properties, 299 properties: Properties,
300 info: InfoRef,
311} 301}
312 302
313impl<'d> Can<'d> { 303impl<'d> Can<'d> {
@@ -341,12 +331,12 @@ impl<'d> Can<'d> {
341 /// can be replaced, this call asynchronously waits for a frame to be successfully 331 /// can be replaced, this call asynchronously waits for a frame to be successfully
342 /// transmitted, then tries again. 332 /// transmitted, then tries again.
343 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { 333 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
344 TxMode::write(self.info, frame).await 334 TxMode::write(&self.info, frame).await
345 } 335 }
346 336
347 /// Returns the next received message frame 337 /// Returns the next received message frame
348 pub async fn read(&mut self) -> Result<Envelope, BusError> { 338 pub async fn read(&mut self) -> Result<Envelope, BusError> {
349 RxMode::read_classic(self.info).await 339 RxMode::read_classic(&self.info).await
350 } 340 }
351 341
352 /// Queues the message to be sent but exerts backpressure. If a lower-priority 342 /// Queues the message to be sent but exerts backpressure. If a lower-priority
@@ -354,29 +344,27 @@ impl<'d> Can<'d> {
354 /// can be replaced, this call asynchronously waits for a frame to be successfully 344 /// can be replaced, this call asynchronously waits for a frame to be successfully
355 /// transmitted, then tries again. 345 /// transmitted, then tries again.
356 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { 346 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
357 TxMode::write_fd(self.info, frame).await 347 TxMode::write_fd(&self.info, frame).await
358 } 348 }
359 349
360 /// Returns the next received message frame 350 /// Returns the next received message frame
361 pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { 351 pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
362 RxMode::read_fd(self.info).await 352 RxMode::read_fd(&self.info).await
363 } 353 }
364 354
365 /// Split instance into separate portions: Tx(write), Rx(read), common properties 355 /// Split instance into separate portions: Tx(write), Rx(read), common properties
366 pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { 356 pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) {
367 (self.info.internal_operation)(InternalOperation::NotifySenderCreated);
368 (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
369 ( 357 (
370 CanTx { 358 CanTx {
371 _phantom: PhantomData, 359 _phantom: PhantomData,
372 info: self.info,
373 config: self.config, 360 config: self.config,
374 _mode: self._mode, 361 _mode: self._mode,
362 info: TxInfoRef::new(&self.info),
375 }, 363 },
376 CanRx { 364 CanRx {
377 _phantom: PhantomData, 365 _phantom: PhantomData,
378 info: self.info,
379 _mode: self._mode, 366 _mode: self._mode,
367 info: RxInfoRef::new(&self.info),
380 }, 368 },
381 Properties { 369 Properties {
382 info: self.properties.info, 370 info: self.properties.info,
@@ -385,14 +373,12 @@ impl<'d> Can<'d> {
385 } 373 }
386 /// Join split rx and tx portions back together 374 /// Join split rx and tx portions back together
387 pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { 375 pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self {
388 (tx.info.internal_operation)(InternalOperation::NotifySenderCreated);
389 (tx.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
390 Can { 376 Can {
391 _phantom: PhantomData, 377 _phantom: PhantomData,
392 config: tx.config, 378 config: tx.config,
393 info: tx.info,
394 _mode: rx._mode, 379 _mode: rx._mode,
395 properties: Properties::new(tx.info), 380 properties: Properties::new(&tx.info),
381 info: InfoRef::new(&tx.info),
396 } 382 }
397 } 383 }
398 384
@@ -402,7 +388,7 @@ impl<'d> Can<'d> {
402 tx_buf: &'static mut TxBuf<TX_BUF_SIZE>, 388 tx_buf: &'static mut TxBuf<TX_BUF_SIZE>,
403 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 389 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
404 ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { 390 ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
405 BufferedCan::new(self.info, self._mode, tx_buf, rxb) 391 BufferedCan::new(&self.info, self._mode, tx_buf, rxb)
406 } 392 }
407 393
408 /// Return a buffered instance of driver with CAN FD support. User must supply Buffers 394 /// Return a buffered instance of driver with CAN FD support. User must supply Buffers
@@ -411,14 +397,7 @@ impl<'d> Can<'d> {
411 tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>, 397 tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>,
412 rxb: &'static mut RxFdBuf<RX_BUF_SIZE>, 398 rxb: &'static mut RxFdBuf<RX_BUF_SIZE>,
413 ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { 399 ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
414 BufferedCanFd::new(self.info, self._mode, tx_buf, rxb) 400 BufferedCanFd::new(&self.info, self._mode, tx_buf, rxb)
415 }
416}
417
418impl<'d> Drop for Can<'d> {
419 fn drop(&mut self) {
420 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
421 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
422 } 401 }
423} 402}
424 403
@@ -431,11 +410,11 @@ pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame,
431/// Buffered FDCAN Instance 410/// Buffered FDCAN Instance
432pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { 411pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
433 _phantom: PhantomData<&'d ()>, 412 _phantom: PhantomData<&'d ()>,
434 info: &'static Info,
435 _mode: OperatingMode, 413 _mode: OperatingMode,
436 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 414 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
437 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 415 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
438 properties: Properties, 416 properties: Properties,
417 info: InfoRef,
439} 418}
440 419
441impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { 420impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
@@ -445,15 +424,13 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d,
445 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 424 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
446 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 425 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
447 ) -> Self { 426 ) -> Self {
448 (info.internal_operation)(InternalOperation::NotifySenderCreated);
449 (info.internal_operation)(InternalOperation::NotifyReceiverCreated);
450 BufferedCan { 427 BufferedCan {
451 _phantom: PhantomData, 428 _phantom: PhantomData,
452 info,
453 _mode, 429 _mode,
454 tx_buf, 430 tx_buf,
455 rx_buf, 431 rx_buf,
456 properties: Properties::new(info), 432 properties: Properties::new(info),
433 info: InfoRef::new(info),
457 } 434 }
458 .setup() 435 .setup()
459 } 436 }
@@ -492,31 +469,21 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d,
492 469
493 /// Returns a sender that can be used for sending CAN frames. 470 /// Returns a sender that can be used for sending CAN frames.
494 pub fn writer(&self) -> BufferedCanSender { 471 pub fn writer(&self) -> BufferedCanSender {
495 (self.info.internal_operation)(InternalOperation::NotifySenderCreated);
496 BufferedCanSender { 472 BufferedCanSender {
497 tx_buf: self.tx_buf.sender().into(), 473 tx_buf: self.tx_buf.sender().into(),
498 waker: self.info.tx_waker, 474 info: TxInfoRef::new(&self.info),
499 internal_operation: self.info.internal_operation,
500 } 475 }
501 } 476 }
502 477
503 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. 478 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
504 pub fn reader(&self) -> BufferedCanReceiver { 479 pub fn reader(&self) -> BufferedCanReceiver {
505 (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
506 BufferedCanReceiver { 480 BufferedCanReceiver {
507 rx_buf: self.rx_buf.receiver().into(), 481 rx_buf: self.rx_buf.receiver().into(),
508 internal_operation: self.info.internal_operation, 482 info: RxInfoRef::new(&self.info),
509 } 483 }
510 } 484 }
511} 485}
512 486
513impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
514 fn drop(&mut self) {
515 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
516 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
517 }
518}
519
520/// User supplied buffer for RX Buffering 487/// User supplied buffer for RX Buffering
521pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>; 488pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>;
522 489
@@ -532,11 +499,11 @@ pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnve
532/// Buffered FDCAN Instance 499/// Buffered FDCAN Instance
533pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { 500pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
534 _phantom: PhantomData<&'d ()>, 501 _phantom: PhantomData<&'d ()>,
535 info: &'static Info,
536 _mode: OperatingMode, 502 _mode: OperatingMode,
537 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 503 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
538 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 504 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
539 properties: Properties, 505 properties: Properties,
506 info: InfoRef,
540} 507}
541 508
542impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { 509impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
@@ -546,15 +513,13 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'
546 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 513 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
547 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 514 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
548 ) -> Self { 515 ) -> Self {
549 (info.internal_operation)(InternalOperation::NotifySenderCreated);
550 (info.internal_operation)(InternalOperation::NotifyReceiverCreated);
551 BufferedCanFd { 516 BufferedCanFd {
552 _phantom: PhantomData, 517 _phantom: PhantomData,
553 info,
554 _mode, 518 _mode,
555 tx_buf, 519 tx_buf,
556 rx_buf, 520 rx_buf,
557 properties: Properties::new(info), 521 properties: Properties::new(info),
522 info: InfoRef::new(info),
558 } 523 }
559 .setup() 524 .setup()
560 } 525 }
@@ -593,36 +558,26 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'
593 558
594 /// Returns a sender that can be used for sending CAN frames. 559 /// Returns a sender that can be used for sending CAN frames.
595 pub fn writer(&self) -> BufferedFdCanSender { 560 pub fn writer(&self) -> BufferedFdCanSender {
596 (self.info.internal_operation)(InternalOperation::NotifySenderCreated);
597 BufferedFdCanSender { 561 BufferedFdCanSender {
598 tx_buf: self.tx_buf.sender().into(), 562 tx_buf: self.tx_buf.sender().into(),
599 waker: self.info.tx_waker, 563 info: TxInfoRef::new(&self.info),
600 internal_operation: self.info.internal_operation,
601 } 564 }
602 } 565 }
603 566
604 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. 567 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
605 pub fn reader(&self) -> BufferedFdCanReceiver { 568 pub fn reader(&self) -> BufferedFdCanReceiver {
606 (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
607 BufferedFdCanReceiver { 569 BufferedFdCanReceiver {
608 rx_buf: self.rx_buf.receiver().into(), 570 rx_buf: self.rx_buf.receiver().into(),
609 internal_operation: self.info.internal_operation, 571 info: RxInfoRef::new(&self.info),
610 } 572 }
611 } 573 }
612} 574}
613 575
614impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
615 fn drop(&mut self) {
616 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
617 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
618 }
619}
620
621/// FDCAN Rx only Instance 576/// FDCAN Rx only Instance
622pub struct CanRx<'d> { 577pub struct CanRx<'d> {
623 _phantom: PhantomData<&'d ()>, 578 _phantom: PhantomData<&'d ()>,
624 info: &'static Info,
625 _mode: OperatingMode, 579 _mode: OperatingMode,
580 info: RxInfoRef,
626} 581}
627 582
628impl<'d> CanRx<'d> { 583impl<'d> CanRx<'d> {
@@ -637,18 +592,12 @@ impl<'d> CanRx<'d> {
637 } 592 }
638} 593}
639 594
640impl<'d> Drop for CanRx<'d> {
641 fn drop(&mut self) {
642 (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
643 }
644}
645
646/// FDCAN Tx only Instance 595/// FDCAN Tx only Instance
647pub struct CanTx<'d> { 596pub struct CanTx<'d> {
648 _phantom: PhantomData<&'d ()>, 597 _phantom: PhantomData<&'d ()>,
649 info: &'static Info,
650 config: crate::can::fd::config::FdCanConfig, 598 config: crate::can::fd::config::FdCanConfig,
651 _mode: OperatingMode, 599 _mode: OperatingMode,
600 info: TxInfoRef,
652} 601}
653 602
654impl<'c, 'd> CanTx<'d> { 603impl<'c, 'd> CanTx<'d> {
@@ -657,7 +606,7 @@ impl<'c, 'd> CanTx<'d> {
657 /// can be replaced, this call asynchronously waits for a frame to be successfully 606 /// can be replaced, this call asynchronously waits for a frame to be successfully
658 /// transmitted, then tries again. 607 /// transmitted, then tries again.
659 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { 608 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
660 TxMode::write(self.info, frame).await 609 TxMode::write(&self.info, frame).await
661 } 610 }
662 611
663 /// Queues the message to be sent but exerts backpressure. If a lower-priority 612 /// Queues the message to be sent but exerts backpressure. If a lower-priority
@@ -665,13 +614,7 @@ impl<'c, 'd> CanTx<'d> {
665 /// can be replaced, this call asynchronously waits for a frame to be successfully 614 /// can be replaced, this call asynchronously waits for a frame to be successfully
666 /// transmitted, then tries again. 615 /// transmitted, then tries again.
667 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { 616 pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
668 TxMode::write_fd(self.info, frame).await 617 TxMode::write_fd(&self.info, frame).await
669 }
670}
671
672impl<'d> Drop for CanTx<'d> {
673 fn drop(&mut self) {
674 (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
675 } 618 }
676} 619}
677 620
@@ -938,21 +881,56 @@ impl State {
938} 881}
939 882
940type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<State>>; 883type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<State>>;
941struct Info { 884pub(crate) struct Info {
942 regs: Registers, 885 regs: Registers,
943 interrupt0: crate::interrupt::Interrupt, 886 interrupt0: crate::interrupt::Interrupt,
944 _interrupt1: crate::interrupt::Interrupt, 887 _interrupt1: crate::interrupt::Interrupt,
945 tx_waker: fn(), 888 pub(crate) tx_waker: fn(),
946 internal_operation: fn(InternalOperation),
947 state: SharedState, 889 state: SharedState,
948} 890}
949 891
892impl Info {
893 pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) {
894 self.state.lock(|s| {
895 let mut mut_state = s.borrow_mut();
896 match val {
897 RefCountOp::NotifySenderCreated => {
898 mut_state.sender_instance_count += 1;
899 }
900 RefCountOp::NotifySenderDestroyed => {
901 mut_state.sender_instance_count -= 1;
902 if 0 == mut_state.sender_instance_count {
903 (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
904 }
905 }
906 RefCountOp::NotifyReceiverCreated => {
907 mut_state.receiver_instance_count += 1;
908 }
909 RefCountOp::NotifyReceiverDestroyed => {
910 mut_state.receiver_instance_count -= 1;
911 if 0 == mut_state.receiver_instance_count {
912 (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
913 }
914 }
915 }
916 if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 {
917 unsafe {
918 let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap());
919 tx_pin.set_as_disconnected();
920 let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap());
921 rx_pin.set_as_disconnected();
922 self.interrupt0.disable();
923 }
924 }
925 });
926 }
927}
928
950trait SealedInstance { 929trait SealedInstance {
951 const MSG_RAM_OFFSET: usize; 930 const MSG_RAM_OFFSET: usize;
952 931
953 fn info() -> &'static Info; 932 fn info() -> &'static Info;
954 fn registers() -> crate::can::fd::peripheral::Registers; 933 fn registers() -> crate::can::fd::peripheral::Registers;
955 fn internal_operation(val: InternalOperation);
956} 934}
957 935
958/// Instance trait 936/// Instance trait
@@ -974,41 +952,6 @@ macro_rules! impl_fdcan {
974 impl SealedInstance for peripherals::$inst { 952 impl SealedInstance for peripherals::$inst {
975 const MSG_RAM_OFFSET: usize = $msg_ram_offset; 953 const MSG_RAM_OFFSET: usize = $msg_ram_offset;
976 954
977 fn internal_operation(val: InternalOperation) {
978 peripherals::$inst::info().state.lock(|s| {
979 let mut mut_state = s.borrow_mut();
980 match val {
981 InternalOperation::NotifySenderCreated => {
982 mut_state.sender_instance_count += 1;
983 }
984 InternalOperation::NotifySenderDestroyed => {
985 mut_state.sender_instance_count -= 1;
986 if ( 0 == mut_state.sender_instance_count) {
987 (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
988 }
989 }
990 InternalOperation::NotifyReceiverCreated => {
991 mut_state.receiver_instance_count += 1;
992 }
993 InternalOperation::NotifyReceiverDestroyed => {
994 mut_state.receiver_instance_count -= 1;
995 if ( 0 == mut_state.receiver_instance_count) {
996 (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
997 }
998 }
999 }
1000 if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 {
1001 unsafe {
1002 let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap());
1003 tx_pin.set_as_disconnected();
1004 let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap());
1005 rx_pin.set_as_disconnected();
1006 rcc::disable::<peripherals::$inst>();
1007 }
1008 }
1009 });
1010 }
1011
1012 fn info() -> &'static Info { 955 fn info() -> &'static Info {
1013 956
1014 static INFO: Info = Info { 957 static INFO: Info = Info {
@@ -1016,7 +959,6 @@ macro_rules! impl_fdcan {
1016 interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, 959 interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ,
1017 _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, 960 _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ,
1018 tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, 961 tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend,
1019 internal_operation: peripherals::$inst::internal_operation,
1020 state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())), 962 state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())),
1021 }; 963 };
1022 &INFO 964 &INFO
diff --git a/embassy-stm32/src/cordic/utils.rs b/embassy-stm32/src/cordic/utils.rs
index 008f50270..9afa8ef53 100644
--- a/embassy-stm32/src/cordic/utils.rs
+++ b/embassy-stm32/src/cordic/utils.rs
@@ -5,7 +5,7 @@ macro_rules! floating_fixed_convert {
5 ($f_to_q:ident, $q_to_f:ident, $unsigned_bin_typ:ty, $signed_bin_typ:ty, $float_ty:ty, $offset:literal, $min_positive:literal) => { 5 ($f_to_q:ident, $q_to_f:ident, $unsigned_bin_typ:ty, $signed_bin_typ:ty, $float_ty:ty, $offset:literal, $min_positive:literal) => {
6 /// convert float point to fixed point format 6 /// convert float point to fixed point format
7 pub fn $f_to_q(value: $float_ty) -> Result<$unsigned_bin_typ, NumberOutOfRange> { 7 pub fn $f_to_q(value: $float_ty) -> Result<$unsigned_bin_typ, NumberOutOfRange> {
8 const MIN_POSITIVE: $float_ty = unsafe { core::mem::transmute($min_positive) }; 8 const MIN_POSITIVE: $float_ty = <$float_ty>::from_bits($min_positive);
9 9
10 if value < -1.0 { 10 if value < -1.0 {
11 return Err(NumberOutOfRange::BelowLowerBound) 11 return Err(NumberOutOfRange::BelowLowerBound)
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs
index fba3c0fd7..35d9f8cce 100644
--- a/embassy-stm32/src/cryp/mod.rs
+++ b/embassy-stm32/src/cryp/mod.rs
@@ -2,7 +2,6 @@
2#[cfg(any(cryp_v2, cryp_v3, cryp_v4))] 2#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
3use core::cmp::min; 3use core::cmp::min;
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::ptr;
6 5
7use embassy_hal_internal::{Peri, PeripheralType}; 6use embassy_hal_internal::{Peri, PeripheralType};
8use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
@@ -1814,14 +1813,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1814 assert_eq!(blocks.len() % block_size, 0); 1813 assert_eq!(blocks.len() % block_size, 0);
1815 // Configure DMA to transfer input to crypto core. 1814 // Configure DMA to transfer input to crypto core.
1816 let dst_ptr: *mut u32 = T::regs().din().as_ptr(); 1815 let dst_ptr: *mut u32 = T::regs().din().as_ptr();
1817 let num_words = blocks.len() / 4;
1818 let src_ptr: *const [u8] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
1819 let options = TransferOptions { 1816 let options = TransferOptions {
1820 #[cfg(not(gpdma))] 1817 #[cfg(not(gpdma))]
1821 priority: crate::dma::Priority::High, 1818 priority: crate::dma::Priority::High,
1822 ..Default::default() 1819 ..Default::default()
1823 }; 1820 };
1824 let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; 1821 let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) };
1825 T::regs().dmacr().modify(|w| w.set_dien(true)); 1822 T::regs().dmacr().modify(|w| w.set_dien(true));
1826 // Wait for the transfer to complete. 1823 // Wait for the transfer to complete.
1827 dma_transfer.await; 1824 dma_transfer.await;
@@ -1836,14 +1833,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1836 assert_eq!((blocks.len() * 4) % block_size, 0); 1833 assert_eq!((blocks.len() * 4) % block_size, 0);
1837 // Configure DMA to transfer input to crypto core. 1834 // Configure DMA to transfer input to crypto core.
1838 let dst_ptr: *mut u32 = T::regs().din().as_ptr(); 1835 let dst_ptr: *mut u32 = T::regs().din().as_ptr();
1839 let num_words = blocks.len();
1840 let src_ptr: *const [u32] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
1841 let options = TransferOptions { 1836 let options = TransferOptions {
1842 #[cfg(not(gpdma))] 1837 #[cfg(not(gpdma))]
1843 priority: crate::dma::Priority::High, 1838 priority: crate::dma::Priority::High,
1844 ..Default::default() 1839 ..Default::default()
1845 }; 1840 };
1846 let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; 1841 let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) };
1847 T::regs().dmacr().modify(|w| w.set_dien(true)); 1842 T::regs().dmacr().modify(|w| w.set_dien(true));
1848 // Wait for the transfer to complete. 1843 // Wait for the transfer to complete.
1849 dma_transfer.await; 1844 dma_transfer.await;
@@ -1857,14 +1852,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1857 assert_eq!(blocks.len() % block_size, 0); 1852 assert_eq!(blocks.len() % block_size, 0);
1858 // Configure DMA to get output from crypto core. 1853 // Configure DMA to get output from crypto core.
1859 let src_ptr = T::regs().dout().as_ptr(); 1854 let src_ptr = T::regs().dout().as_ptr();
1860 let num_words = blocks.len() / 4;
1861 let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words);
1862 let options = TransferOptions { 1855 let options = TransferOptions {
1863 #[cfg(not(gpdma))] 1856 #[cfg(not(gpdma))]
1864 priority: crate::dma::Priority::VeryHigh, 1857 priority: crate::dma::Priority::VeryHigh,
1865 ..Default::default() 1858 ..Default::default()
1866 }; 1859 };
1867 let dma_transfer = unsafe { dma.read_raw(src_ptr, dst_ptr, options) }; 1860 let dma_transfer = unsafe { dma.read_raw(src_ptr, blocks, options) };
1868 T::regs().dmacr().modify(|w| w.set_doen(true)); 1861 T::regs().dmacr().modify(|w| w.set_doen(true));
1869 // Wait for the transfer to complete. 1862 // Wait for the transfer to complete.
1870 dma_transfer.await; 1863 dma_transfer.await;
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 30046849b..d8f1f96f2 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -403,6 +403,46 @@ impl<'d, T: Instance> Dac<'d, T, Async> {
403 Mode::NormalExternalBuffered, 403 Mode::NormalExternalBuffered,
404 ) 404 )
405 } 405 }
406 /// Create a new `Dac` instance with external output pins and unbuffered mode.
407 ///
408 /// This function consumes the underlying DAC peripheral and allows access to both channels.
409 /// The channels are configured for external output with the buffer disabled.
410 ///
411 /// The channels are enabled on creation and begin to drive their output pins.
412 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
413 /// disable the channel; you must re-enable them with `enable()`.
414 ///
415 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
416 /// method on the underlying channels.
417 ///
418 /// # Arguments
419 ///
420 /// * `peri` - The DAC peripheral instance.
421 /// * `dma_ch1` - The DMA channel for DAC channel 1.
422 /// * `dma_ch2` - The DMA channel for DAC channel 2.
423 /// * `pin_ch1` - The GPIO pin for DAC channel 1 output.
424 /// * `pin_ch2` - The GPIO pin for DAC channel 2 output.
425 ///
426 /// # Returns
427 ///
428 /// A new `Dac` instance in unbuffered mode.
429 pub fn new_unbuffered(
430 peri: Peri<'d, T>,
431 dma_ch1: Peri<'d, impl Dma<T, Ch1>>,
432 dma_ch2: Peri<'d, impl Dma<T, Ch2>>,
433 pin_ch1: Peri<'d, impl DacPin<T, Ch1> + crate::gpio::Pin>,
434 pin_ch2: Peri<'d, impl DacPin<T, Ch2> + crate::gpio::Pin>,
435 ) -> Self {
436 pin_ch1.set_as_analog();
437 pin_ch2.set_as_analog();
438 Self::new_inner(
439 peri,
440 new_dma!(dma_ch1),
441 new_dma!(dma_ch2),
442 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
443 Mode::NormalExternalUnbuffered,
444 )
445 }
406 446
407 /// Create a new `Dac` instance where the external output pins are not used, 447 /// Create a new `Dac` instance where the external output pins are not used,
408 /// so the DAC can only be used to generate internal signals but the GPIO 448 /// so the DAC can only be used to generate internal signals but the GPIO
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index 7dbbe7b72..464823bfc 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -341,9 +341,12 @@ impl AnyChannel {
341 mem_len: usize, 341 mem_len: usize,
342 incr_mem: bool, 342 incr_mem: bool,
343 mem_size: WordSize, 343 mem_size: WordSize,
344 peripheral_size: WordSize, 344 peri_size: WordSize,
345 options: TransferOptions, 345 options: TransferOptions,
346 ) { 346 ) {
347 // "Preceding reads and writes cannot be moved past subsequent writes."
348 fence(Ordering::SeqCst);
349
347 let info = self.info(); 350 let info = self.info();
348 #[cfg(feature = "_dual-core")] 351 #[cfg(feature = "_dual-core")]
349 { 352 {
@@ -354,28 +357,48 @@ impl AnyChannel {
354 #[cfg(dmamux)] 357 #[cfg(dmamux)]
355 super::dmamux::configure_dmamux(&info.dmamux, _request); 358 super::dmamux::configure_dmamux(&info.dmamux, _request);
356 359
357 assert!(mem_len > 0 && mem_len <= 0xFFFF);
358
359 match self.info().dma { 360 match self.info().dma {
360 #[cfg(dma)] 361 #[cfg(dma)]
361 DmaInfo::Dma(r) => { 362 DmaInfo::Dma(r) => {
362 let state: &ChannelState = &STATE[self.id as usize]; 363 let state: &ChannelState = &STATE[self.id as usize];
363 let ch = r.st(info.num); 364 let ch = r.st(info.num);
364 365
365 // "Preceding reads and writes cannot be moved past subsequent writes."
366 fence(Ordering::SeqCst);
367
368 state.complete_count.store(0, Ordering::Release); 366 state.complete_count.store(0, Ordering::Release);
369 self.clear_irqs(); 367 self.clear_irqs();
370 368
369 // NDTR is the number of transfers in the *peripheral* word size.
370 // ex: if mem_size=1, peri_size=4 and ndtr=3 it'll do 12 mem transfers, 3 peri transfers.
371 let ndtr = match (mem_size, peri_size) {
372 (WordSize::FourBytes, WordSize::OneByte) => mem_len * 4,
373 (WordSize::FourBytes, WordSize::TwoBytes) | (WordSize::TwoBytes, WordSize::OneByte) => mem_len * 2,
374 (WordSize::FourBytes, WordSize::FourBytes)
375 | (WordSize::TwoBytes, WordSize::TwoBytes)
376 | (WordSize::OneByte, WordSize::OneByte) => mem_len,
377 (WordSize::TwoBytes, WordSize::FourBytes) | (WordSize::OneByte, WordSize::TwoBytes) => {
378 assert!(mem_len % 2 == 0);
379 mem_len / 2
380 }
381 (WordSize::OneByte, WordSize::FourBytes) => {
382 assert!(mem_len % 4 == 0);
383 mem_len / 4
384 }
385 };
386
387 assert!(ndtr > 0 && ndtr <= 0xFFFF);
388
371 ch.par().write_value(peri_addr as u32); 389 ch.par().write_value(peri_addr as u32);
372 ch.m0ar().write_value(mem_addr as u32); 390 ch.m0ar().write_value(mem_addr as u32);
373 ch.ndtr().write_value(pac::dma::regs::Ndtr(mem_len as _)); 391 ch.ndtr().write_value(pac::dma::regs::Ndtr(ndtr as _));
374 ch.fcr().write(|w| { 392 ch.fcr().write(|w| {
375 if let Some(fth) = options.fifo_threshold { 393 if let Some(fth) = options.fifo_threshold {
376 // FIFO mode 394 // FIFO mode
377 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED); 395 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED);
378 w.set_fth(fth.into()); 396 w.set_fth(fth.into());
397 } else if mem_size != peri_size {
398 // force FIFO mode if msize != psize
399 // packing/unpacking doesn't work in direct mode.
400 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED);
401 w.set_fth(FifoThreshold::Half.into());
379 } else { 402 } else {
380 // Direct mode 403 // Direct mode
381 w.set_dmdis(pac::dma::vals::Dmdis::ENABLED); 404 w.set_dmdis(pac::dma::vals::Dmdis::ENABLED);
@@ -384,7 +407,7 @@ impl AnyChannel {
384 ch.cr().write(|w| { 407 ch.cr().write(|w| {
385 w.set_dir(dir.into()); 408 w.set_dir(dir.into());
386 w.set_msize(mem_size.into()); 409 w.set_msize(mem_size.into());
387 w.set_psize(peripheral_size.into()); 410 w.set_psize(peri_size.into());
388 w.set_pl(options.priority.into()); 411 w.set_pl(options.priority.into());
389 w.set_minc(incr_mem); 412 w.set_minc(incr_mem);
390 w.set_pinc(false); 413 w.set_pinc(false);
@@ -404,6 +427,8 @@ impl AnyChannel {
404 } 427 }
405 #[cfg(bdma)] 428 #[cfg(bdma)]
406 DmaInfo::Bdma(r) => { 429 DmaInfo::Bdma(r) => {
430 assert!(mem_len > 0 && mem_len <= 0xFFFF);
431
407 #[cfg(bdma_v2)] 432 #[cfg(bdma_v2)]
408 critical_section::with(|_| r.cselr().modify(|w| w.set_cs(info.num, _request))); 433 critical_section::with(|_| r.cselr().modify(|w| w.set_cs(info.num, _request)));
409 434
@@ -417,7 +442,7 @@ impl AnyChannel {
417 ch.mar().write_value(mem_addr as u32); 442 ch.mar().write_value(mem_addr as u32);
418 ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); 443 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
419 ch.cr().write(|w| { 444 ch.cr().write(|w| {
420 w.set_psize(peripheral_size.into()); 445 w.set_psize(peri_size.into());
421 w.set_msize(mem_size.into()); 446 w.set_msize(mem_size.into());
422 w.set_minc(incr_mem); 447 w.set_minc(incr_mem);
423 w.set_dir(dir.into()); 448 w.set_dir(dir.into());
@@ -587,11 +612,11 @@ impl<'a> Transfer<'a> {
587 } 612 }
588 613
589 /// Create a new read DMA transfer (peripheral to memory), using raw pointers. 614 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
590 pub unsafe fn new_read_raw<W: Word>( 615 pub unsafe fn new_read_raw<MW: Word, PW: Word>(
591 channel: Peri<'a, impl Channel>, 616 channel: Peri<'a, impl Channel>,
592 request: Request, 617 request: Request,
593 peri_addr: *mut W, 618 peri_addr: *mut PW,
594 buf: *mut [W], 619 buf: *mut [MW],
595 options: TransferOptions, 620 options: TransferOptions,
596 ) -> Self { 621 ) -> Self {
597 Self::new_inner( 622 Self::new_inner(
@@ -599,11 +624,11 @@ impl<'a> Transfer<'a> {
599 request, 624 request,
600 Dir::PeripheralToMemory, 625 Dir::PeripheralToMemory,
601 peri_addr as *const u32, 626 peri_addr as *const u32,
602 buf as *mut W as *mut u32, 627 buf as *mut MW as *mut u32,
603 buf.len(), 628 buf.len(),
604 true, 629 true,
605 W::size(), 630 MW::size(),
606 W::size(), 631 PW::size(),
607 options, 632 options,
608 ) 633 )
609 } 634 }
@@ -672,22 +697,14 @@ impl<'a> Transfer<'a> {
672 mem_addr: *mut u32, 697 mem_addr: *mut u32,
673 mem_len: usize, 698 mem_len: usize,
674 incr_mem: bool, 699 incr_mem: bool,
675 data_size: WordSize, 700 mem_size: WordSize,
676 peripheral_size: WordSize, 701 peri_size: WordSize,
677 options: TransferOptions, 702 options: TransferOptions,
678 ) -> Self { 703 ) -> Self {
679 assert!(mem_len > 0 && mem_len <= 0xFFFF); 704 assert!(mem_len > 0 && mem_len <= 0xFFFF);
680 705
681 channel.configure( 706 channel.configure(
682 _request, 707 _request, dir, peri_addr, mem_addr, mem_len, incr_mem, mem_size, peri_size, options,
683 dir,
684 peri_addr,
685 mem_addr,
686 mem_len,
687 incr_mem,
688 data_size,
689 peripheral_size,
690 options,
691 ); 708 );
692 channel.start(); 709 channel.start();
693 Self { channel } 710 Self { channel }
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index ade70fb55..151e4ab9f 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -125,11 +125,11 @@ impl<'a> Transfer<'a> {
125 } 125 }
126 126
127 /// Create a new read DMA transfer (peripheral to memory), using raw pointers. 127 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
128 pub unsafe fn new_read_raw<W: Word>( 128 pub unsafe fn new_read_raw<MW: Word, PW: Word>(
129 channel: Peri<'a, impl Channel>, 129 channel: Peri<'a, impl Channel>,
130 request: Request, 130 request: Request,
131 peri_addr: *mut W, 131 peri_addr: *mut PW,
132 buf: *mut [W], 132 buf: *mut [MW],
133 options: TransferOptions, 133 options: TransferOptions,
134 ) -> Self { 134 ) -> Self {
135 Self::new_inner( 135 Self::new_inner(
@@ -137,11 +137,11 @@ impl<'a> Transfer<'a> {
137 request, 137 request,
138 Dir::PeripheralToMemory, 138 Dir::PeripheralToMemory,
139 peri_addr as *const u32, 139 peri_addr as *const u32,
140 buf as *mut W as *mut u32, 140 buf as *mut MW as *mut u32,
141 buf.len(), 141 buf.len(),
142 true, 142 true,
143 W::size(), 143 PW::size(),
144 W::size(), 144 MW::size(),
145 options, 145 options,
146 ) 146 )
147 } 147 }
diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs
index 8bf89e2fe..3245887c1 100644
--- a/embassy-stm32/src/dma/util.rs
+++ b/embassy-stm32/src/dma/util.rs
@@ -20,10 +20,10 @@ impl<'d> ChannelAndRequest<'d> {
20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options) 20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options)
21 } 21 }
22 22
23 pub unsafe fn read_raw<'a, W: Word>( 23 pub unsafe fn read_raw<'a, MW: Word, PW: Word>(
24 &'a mut self, 24 &'a mut self,
25 peri_addr: *mut W, 25 peri_addr: *mut PW,
26 buf: *mut [W], 26 buf: *mut [MW],
27 options: TransferOptions, 27 options: TransferOptions,
28 ) -> Transfer<'a> { 28 ) -> Transfer<'a> {
29 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options) 29 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options)
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 01e321bce..b9746231f 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -122,7 +122,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
122 122
123 // Select RMII (Reduced Media Independent Interface) 123 // Select RMII (Reduced Media Independent Interface)
124 // Must be done prior to enabling peripheral clock 124 // Must be done prior to enabling peripheral clock
125 AFIO.mapr().modify(|w| w.set_mii_rmii_sel(true)); 125 AFIO.mapr().modify(|w| {
126 w.set_mii_rmii_sel(true);
127 w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
128 });
126 129
127 RCC.ahbenr().modify(|w| { 130 RCC.ahbenr().modify(|w| {
128 w.set_ethen(true); 131 w.set_ethen(true);
@@ -316,7 +319,10 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
316 319
317 // Select MII (Media Independent Interface) 320 // Select MII (Media Independent Interface)
318 // Must be done prior to enabling peripheral clock 321 // Must be done prior to enabling peripheral clock
319 AFIO.mapr().modify(|w| w.set_mii_rmii_sel(false)); 322 AFIO.mapr().modify(|w| {
323 w.set_mii_rmii_sel(false);
324 w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
325 });
320 326
321 RCC.ahbenr().modify(|w| { 327 RCC.ahbenr().modify(|w| {
322 w.set_ethen(true); 328 w.set_ethen(true);
diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs
index 131caa195..6c3d4b422 100644
--- a/embassy-stm32/src/flash/u5.rs
+++ b/embassy-stm32/src/flash/u5.rs
@@ -30,19 +30,19 @@ pub(crate) unsafe fn enable_blocking_write() {
30 30
31 #[cfg(feature = "trustzone-secure")] 31 #[cfg(feature = "trustzone-secure")]
32 pac::FLASH.seccr().write(|w| { 32 pac::FLASH.seccr().write(|w| {
33 w.set_pg(pac::flash::vals::SeccrPg::B_0X1); 33 w.set_pg(true);
34 }); 34 });
35 #[cfg(not(feature = "trustzone-secure"))] 35 #[cfg(not(feature = "trustzone-secure"))]
36 pac::FLASH.nscr().write(|w| { 36 pac::FLASH.nscr().write(|w| {
37 w.set_pg(pac::flash::vals::NscrPg::B_0X1); 37 w.set_pg(true);
38 }); 38 });
39} 39}
40 40
41pub(crate) unsafe fn disable_blocking_write() { 41pub(crate) unsafe fn disable_blocking_write() {
42 #[cfg(feature = "trustzone-secure")] 42 #[cfg(feature = "trustzone-secure")]
43 pac::FLASH.seccr().write(|w| w.set_pg(pac::flash::vals::SeccrPg::B_0X0)); 43 pac::FLASH.seccr().write(|w| w.set_pg(false));
44 #[cfg(not(feature = "trustzone-secure"))] 44 #[cfg(not(feature = "trustzone-secure"))]
45 pac::FLASH.nscr().write(|w| w.set_pg(pac::flash::vals::NscrPg::B_0X0)); 45 pac::FLASH.nscr().write(|w| w.set_pg(false));
46} 46}
47 47
48pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { 48pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
@@ -65,19 +65,19 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
65 w.set_pnb(sector.index_in_bank); 65 w.set_pnb(sector.index_in_bank);
66 // TODO: add check for bank swap 66 // TODO: add check for bank swap
67 w.set_bker(match sector.bank { 67 w.set_bker(match sector.bank {
68 FlashBank::Bank1 => pac::flash::vals::SeccrBker::B_0X0, 68 FlashBank::Bank1 => false,
69 FlashBank::Bank2 => pac::flash::vals::SeccrBker::B_0X1, 69 FlashBank::Bank2 => true,
70 _ => unreachable!(), 70 _ => unreachable!(),
71 }); 71 });
72 }); 72 });
73 #[cfg(not(feature = "trustzone-secure"))] 73 #[cfg(not(feature = "trustzone-secure"))]
74 pac::FLASH.nscr().modify(|w| { 74 pac::FLASH.nscr().modify(|w| {
75 w.set_per(pac::flash::vals::NscrPer::B_0X1); 75 w.set_per(true);
76 w.set_pnb(sector.index_in_bank); 76 w.set_pnb(sector.index_in_bank);
77 // TODO: add check for bank swap 77 // TODO: add check for bank swap
78 w.set_bker(match sector.bank { 78 w.set_bker(match sector.bank {
79 FlashBank::Bank1 => pac::flash::vals::NscrBker::B_0X0, 79 FlashBank::Bank1 => false,
80 FlashBank::Bank2 => pac::flash::vals::NscrBker::B_0X1, 80 FlashBank::Bank2 => true,
81 _ => unreachable!(), 81 _ => unreachable!(),
82 }); 82 });
83 }); 83 });
@@ -93,13 +93,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
93 93
94 let ret: Result<(), Error> = blocking_wait_ready(); 94 let ret: Result<(), Error> = blocking_wait_ready();
95 #[cfg(feature = "trustzone-secure")] 95 #[cfg(feature = "trustzone-secure")]
96 pac::FLASH 96 pac::FLASH.seccr().modify(|w| w.set_per(false));
97 .seccr()
98 .modify(|w| w.set_per(pac::flash::vals::SeccrPer::B_0X0));
99 #[cfg(not(feature = "trustzone-secure"))] 97 #[cfg(not(feature = "trustzone-secure"))]
100 pac::FLASH 98 pac::FLASH.nscr().modify(|w| w.set_per(false));
101 .nscr()
102 .modify(|w| w.set_per(pac::flash::vals::NscrPer::B_0X0));
103 clear_all_err(); 99 clear_all_err();
104 ret 100 ret
105} 101}
diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs
index 31527bcdb..573a1851d 100644
--- a/embassy-stm32/src/hsem/mod.rs
+++ b/embassy-stm32/src/hsem/mod.rs
@@ -3,7 +3,7 @@
3use embassy_hal_internal::PeripheralType; 3use embassy_hal_internal::PeripheralType;
4 4
5use crate::pac; 5use crate::pac;
6use crate::rcc::RccPeripheral; 6use crate::rcc::{self, RccPeripheral};
7// TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs. 7// TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs.
8// Those MCUs have a different HSEM implementation (Secure semaphore lock support, 8// Those MCUs have a different HSEM implementation (Secure semaphore lock support,
9// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute), 9// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute),
@@ -46,7 +46,7 @@ pub enum CoreId {
46#[inline(always)] 46#[inline(always)]
47pub fn get_current_coreid() -> CoreId { 47pub fn get_current_coreid() -> CoreId {
48 let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() }; 48 let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() };
49 match cpuid & 0x000000F0 { 49 match (cpuid & 0x000000F0) >> 4 {
50 #[cfg(any(stm32wb, stm32wl))] 50 #[cfg(any(stm32wb, stm32wl))]
51 0x0 => CoreId::Core1, 51 0x0 => CoreId::Core1,
52 52
@@ -80,6 +80,8 @@ pub struct HardwareSemaphore<'d, T: Instance> {
80impl<'d, T: Instance> HardwareSemaphore<'d, T> { 80impl<'d, T: Instance> HardwareSemaphore<'d, T> {
81 /// Creates a new HardwareSemaphore instance. 81 /// Creates a new HardwareSemaphore instance.
82 pub fn new(peripheral: Peri<'d, T>) -> Self { 82 pub fn new(peripheral: Peri<'d, T>) -> Self {
83 rcc::enable_and_reset::<T>();
84
83 HardwareSemaphore { _peri: peripheral } 85 HardwareSemaphore { _peri: peripheral }
84 } 86 }
85 87
diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs
new file mode 100644
index 000000000..daae43bcd
--- /dev/null
+++ b/embassy-stm32/src/i2c/config.rs
@@ -0,0 +1,170 @@
1#[cfg(gpio_v2)]
2use crate::gpio::Pull;
3use crate::gpio::{AfType, OutputType, Speed};
4
5#[repr(u8)]
6#[derive(Copy, Clone)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8/// Bits of the I2C OA2 register to mask out.
9pub enum AddrMask {
10 /// No mask
11 NOMASK,
12 /// OA2\[1\] is masked and don’t care. Only OA2\[7:2\] are compared.
13 MASK1,
14 /// OA2\[2:1\] are masked and don’t care. Only OA2\[7:3\] are compared.
15 MASK2,
16 /// OA2\[3:1\] are masked and don’t care. Only OA2\[7:4\] are compared.
17 MASK3,
18 /// OA2\[4:1\] are masked and don’t care. Only OA2\[7:5\] are compared.
19 MASK4,
20 /// OA2\[5:1\] are masked and don’t care. Only OA2\[7:6\] are compared.
21 MASK5,
22 /// OA2\[6:1\] are masked and don’t care. Only OA2\[7:6\] are compared.
23 MASK6,
24 /// OA2\[7:1\] are masked and don’t care. No comparison is done, and all (except reserved) 7-bit received addresses are acknowledged
25 MASK7,
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30/// An I2C address. Either 7 or 10 bit.
31pub enum Address {
32 /// A 7 bit address
33 SevenBit(u8),
34 /// A 10 bit address.
35 ///
36 /// When using an address to configure the Own Address, only the OA1 register can be set to a 10-bit address.
37 TenBit(u16),
38}
39impl From<u8> for Address {
40 fn from(value: u8) -> Self {
41 Address::SevenBit(value)
42 }
43}
44impl From<u16> for Address {
45 fn from(value: u16) -> Self {
46 assert!(value < 0x400, "Ten bit address must be less than 0x400");
47 Address::TenBit(value)
48 }
49}
50impl Address {
51 /// Get the inner address as a u16.
52 ///
53 /// For 7 bit addresses, the u8 that was used to store the address is returned as a u16.
54 pub fn addr(&self) -> u16 {
55 match self {
56 Address::SevenBit(addr) => *addr as u16,
57 Address::TenBit(addr) => *addr,
58 }
59 }
60}
61
62#[derive(Copy, Clone)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64/// The second Own Address register.
65pub struct OA2 {
66 /// The address.
67 pub addr: u8,
68 /// The bit mask that will affect how the own address 2 register is compared.
69 pub mask: AddrMask,
70}
71
72#[derive(Copy, Clone)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74/// The Own Address(es) of the I2C peripheral.
75pub enum OwnAddresses {
76 /// Configuration for only the OA1 register.
77 OA1(Address),
78 /// Configuration for only the OA2 register.
79 OA2(OA2),
80 /// Configuration for both the OA1 and OA2 registers.
81 Both {
82 /// The [Address] for the OA1 register.
83 oa1: Address,
84 /// The [OA2] configuration.
85 oa2: OA2,
86 },
87}
88
89/// Slave Configuration
90#[derive(Copy, Clone)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92pub struct SlaveAddrConfig {
93 /// Target Address(es)
94 pub addr: OwnAddresses,
95 /// Control if the peripheral should respond to the general call address
96 pub general_call: bool,
97}
98impl SlaveAddrConfig {
99 /// Create a new slave address configuration with only the OA1 register set in 7 bit mode and the general call disabled.
100 pub fn basic(addr: u8) -> Self {
101 Self {
102 addr: OwnAddresses::OA1(Address::SevenBit(addr)),
103 general_call: false,
104 }
105 }
106}
107
108/// I2C config
109#[non_exhaustive]
110#[derive(Copy, Clone)]
111pub struct Config {
112 /// Enable internal pullup on SDA.
113 ///
114 /// Using external pullup resistors is recommended for I2C. If you do
115 /// have external pullups you should not enable this.
116 #[cfg(gpio_v2)]
117 pub sda_pullup: bool,
118 /// Enable internal pullup on SCL.
119 ///
120 /// Using external pullup resistors is recommended for I2C. If you do
121 /// have external pullups you should not enable this.
122 #[cfg(gpio_v2)]
123 pub scl_pullup: bool,
124 /// Timeout.
125 #[cfg(feature = "time")]
126 pub timeout: embassy_time::Duration,
127}
128
129impl Default for Config {
130 fn default() -> Self {
131 Self {
132 #[cfg(gpio_v2)]
133 sda_pullup: false,
134 #[cfg(gpio_v2)]
135 scl_pullup: false,
136 #[cfg(feature = "time")]
137 timeout: embassy_time::Duration::from_millis(1000),
138 }
139 }
140}
141
142impl Config {
143 pub(super) fn scl_af(&self) -> AfType {
144 #[cfg(gpio_v1)]
145 return AfType::output(OutputType::OpenDrain, Speed::Medium);
146 #[cfg(gpio_v2)]
147 return AfType::output_pull(
148 OutputType::OpenDrain,
149 Speed::Medium,
150 match self.scl_pullup {
151 true => Pull::Up,
152 false => Pull::Down,
153 },
154 );
155 }
156
157 pub(super) fn sda_af(&self) -> AfType {
158 #[cfg(gpio_v1)]
159 return AfType::output(OutputType::OpenDrain, Speed::Medium);
160 #[cfg(gpio_v2)]
161 return AfType::output_pull(
162 OutputType::OpenDrain,
163 Speed::Medium,
164 match self.sda_pullup {
165 true => Pull::Up,
166 false => Pull::Down,
167 },
168 );
169 }
170}
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 1689fdb84..825dd240c 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -5,19 +5,22 @@
5#[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")] 5#[cfg_attr(any(i2c_v2, i2c_v3), path = "v2.rs")]
6mod _version; 6mod _version;
7 7
8mod config;
9
8use core::future::Future; 10use core::future::Future;
9use core::iter; 11use core::iter;
10use core::marker::PhantomData; 12use core::marker::PhantomData;
11 13
14pub use config::*;
12use embassy_hal_internal::Peri; 15use embassy_hal_internal::Peri;
13use embassy_sync::waitqueue::AtomicWaker; 16use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")] 17#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant}; 18use embassy_time::{Duration, Instant};
19use mode::MasterMode;
20pub use mode::{Master, MultiMaster};
16 21
17use crate::dma::ChannelAndRequest; 22use crate::dma::ChannelAndRequest;
18#[cfg(gpio_v2)] 23use crate::gpio::{AnyPin, SealedPin as _};
19use crate::gpio::Pull;
20use crate::gpio::{AfType, AnyPin, OutputType, SealedPin as _, Speed};
21use crate::interrupt::typelevel::Interrupt; 24use crate::interrupt::typelevel::Interrupt;
22use crate::mode::{Async, Blocking, Mode}; 25use crate::mode::{Async, Blocking, Mode};
23use crate::rcc::{RccInfo, SealedRccPeripheral}; 26use crate::rcc::{RccInfo, SealedRccPeripheral};
@@ -62,85 +65,89 @@ impl core::fmt::Display for Error {
62 65
63impl core::error::Error for Error {} 66impl core::error::Error for Error {}
64 67
65/// I2C config 68/// I2C modes
66#[non_exhaustive] 69pub mod mode {
67#[derive(Copy, Clone)] 70 trait SealedMode {}
68pub struct Config { 71
69 /// Enable internal pullup on SDA. 72 /// Trait for I2C master operations.
70 /// 73 #[allow(private_bounds)]
71 /// Using external pullup resistors is recommended for I2C. If you do 74 pub trait MasterMode: SealedMode {}
72 /// have external pullups you should not enable this. 75
73 #[cfg(gpio_v2)] 76 /// Mode allowing for I2C master operations.
74 pub sda_pullup: bool, 77 pub struct Master;
75 /// Enable internal pullup on SCL. 78 /// Mode allowing for I2C master and slave operations.
76 /// 79 pub struct MultiMaster;
77 /// Using external pullup resistors is recommended for I2C. If you do 80
78 /// have external pullups you should not enable this. 81 impl SealedMode for Master {}
79 #[cfg(gpio_v2)] 82 impl MasterMode for Master {}
80 pub scl_pullup: bool, 83
81 /// Timeout. 84 impl SealedMode for MultiMaster {}
82 #[cfg(feature = "time")] 85 impl MasterMode for MultiMaster {}
83 pub timeout: embassy_time::Duration,
84} 86}
85 87
86impl Default for Config { 88#[derive(Debug, Clone, PartialEq, Eq)]
87 fn default() -> Self { 89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88 Self { 90/// The command kind to the slave from the master
89 #[cfg(gpio_v2)] 91pub enum SlaveCommandKind {
90 sda_pullup: false, 92 /// Write to the slave
91 #[cfg(gpio_v2)] 93 Write,
92 scl_pullup: false, 94 /// Read from the slave
93 #[cfg(feature = "time")] 95 Read,
94 timeout: embassy_time::Duration::from_millis(1000),
95 }
96 }
97} 96}
98 97
99impl Config { 98#[derive(Debug, Clone, PartialEq, Eq)]
100 fn scl_af(&self) -> AfType { 99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
101 #[cfg(gpio_v1)] 100/// The command kind to the slave from the master and the address that the slave matched
102 return AfType::output(OutputType::OpenDrain, Speed::Medium); 101pub struct SlaveCommand {
103 #[cfg(gpio_v2)] 102 /// The kind of command
104 return AfType::output_pull( 103 pub kind: SlaveCommandKind,
105 OutputType::OpenDrain, 104 /// The address that the slave matched
106 Speed::Medium, 105 pub address: Address,
107 match self.scl_pullup { 106}
108 true => Pull::Up,
109 false => Pull::None,
110 },
111 );
112 }
113 107
114 fn sda_af(&self) -> AfType { 108#[derive(Debug, Clone, PartialEq, Eq)]
115 #[cfg(gpio_v1)] 109#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116 return AfType::output(OutputType::OpenDrain, Speed::Medium); 110/// The status of the slave send operation
117 #[cfg(gpio_v2)] 111pub enum SendStatus {
118 return AfType::output_pull( 112 /// The slave send operation is done, all bytes have been sent and the master is not requesting more
119 OutputType::OpenDrain, 113 Done,
120 Speed::Medium, 114 /// The slave send operation is done, but there are leftover bytes that the master did not read
121 match self.sda_pullup { 115 LeftoverBytes(usize),
122 true => Pull::Up, 116}
123 false => Pull::None, 117
124 }, 118struct I2CDropGuard<'d> {
125 ); 119 info: &'static Info,
120 scl: Option<Peri<'d, AnyPin>>,
121 sda: Option<Peri<'d, AnyPin>>,
122}
123impl<'d> Drop for I2CDropGuard<'d> {
124 fn drop(&mut self) {
125 if let Some(x) = self.scl.as_ref() {
126 x.set_as_disconnected()
127 }
128 if let Some(x) = self.sda.as_ref() {
129 x.set_as_disconnected()
130 }
131
132 self.info.rcc.disable();
126 } 133 }
127} 134}
128 135
129/// I2C driver. 136/// I2C driver.
130pub struct I2c<'d, M: Mode> { 137pub struct I2c<'d, M: Mode, IM: MasterMode> {
131 info: &'static Info, 138 info: &'static Info,
132 state: &'static State, 139 state: &'static State,
133 kernel_clock: Hertz, 140 kernel_clock: Hertz,
134 scl: Option<Peri<'d, AnyPin>>,
135 sda: Option<Peri<'d, AnyPin>>,
136 tx_dma: Option<ChannelAndRequest<'d>>, 141 tx_dma: Option<ChannelAndRequest<'d>>,
137 rx_dma: Option<ChannelAndRequest<'d>>, 142 rx_dma: Option<ChannelAndRequest<'d>>,
138 #[cfg(feature = "time")] 143 #[cfg(feature = "time")]
139 timeout: Duration, 144 timeout: Duration,
140 _phantom: PhantomData<M>, 145 _phantom: PhantomData<M>,
146 _phantom2: PhantomData<IM>,
147 _drop_guard: I2CDropGuard<'d>,
141} 148}
142 149
143impl<'d> I2c<'d, Async> { 150impl<'d> I2c<'d, Async, Master> {
144 /// Create a new I2C driver. 151 /// Create a new I2C driver.
145 pub fn new<T: Instance>( 152 pub fn new<T: Instance>(
146 peri: Peri<'d, T>, 153 peri: Peri<'d, T>,
@@ -166,7 +173,7 @@ impl<'d> I2c<'d, Async> {
166 } 173 }
167} 174}
168 175
169impl<'d> I2c<'d, Blocking> { 176impl<'d> I2c<'d, Blocking, Master> {
170 /// Create a new blocking I2C driver. 177 /// Create a new blocking I2C driver.
171 pub fn new_blocking<T: Instance>( 178 pub fn new_blocking<T: Instance>(
172 peri: Peri<'d, T>, 179 peri: Peri<'d, T>,
@@ -187,7 +194,7 @@ impl<'d> I2c<'d, Blocking> {
187 } 194 }
188} 195}
189 196
190impl<'d, M: Mode> I2c<'d, M> { 197impl<'d, M: Mode> I2c<'d, M, Master> {
191 /// Create a new I2C driver. 198 /// Create a new I2C driver.
192 fn new_inner<T: Instance>( 199 fn new_inner<T: Instance>(
193 _peri: Peri<'d, T>, 200 _peri: Peri<'d, T>,
@@ -205,15 +212,20 @@ impl<'d, M: Mode> I2c<'d, M> {
205 info: T::info(), 212 info: T::info(),
206 state: T::state(), 213 state: T::state(),
207 kernel_clock: T::frequency(), 214 kernel_clock: T::frequency(),
208 scl,
209 sda,
210 tx_dma, 215 tx_dma,
211 rx_dma, 216 rx_dma,
212 #[cfg(feature = "time")] 217 #[cfg(feature = "time")]
213 timeout: config.timeout, 218 timeout: config.timeout,
214 _phantom: PhantomData, 219 _phantom: PhantomData,
220 _phantom2: PhantomData,
221 _drop_guard: I2CDropGuard {
222 info: T::info(),
223 scl,
224 sda,
225 },
215 }; 226 };
216 this.enable_and_init(freq, config); 227 this.enable_and_init(freq, config);
228
217 this 229 this
218 } 230 }
219 231
@@ -221,7 +233,9 @@ impl<'d, M: Mode> I2c<'d, M> {
221 self.info.rcc.enable_and_reset(); 233 self.info.rcc.enable_and_reset();
222 self.init(freq, config); 234 self.init(freq, config);
223 } 235 }
236}
224 237
238impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
225 fn timeout(&self) -> Timeout { 239 fn timeout(&self) -> Timeout {
226 Timeout { 240 Timeout {
227 #[cfg(feature = "time")] 241 #[cfg(feature = "time")]
@@ -230,15 +244,6 @@ impl<'d, M: Mode> I2c<'d, M> {
230 } 244 }
231} 245}
232 246
233impl<'d, M: Mode> Drop for I2c<'d, M> {
234 fn drop(&mut self) {
235 self.scl.as_ref().map(|x| x.set_as_disconnected());
236 self.sda.as_ref().map(|x| x.set_as_disconnected());
237
238 self.info.rcc.disable()
239 }
240}
241
242#[derive(Copy, Clone)] 247#[derive(Copy, Clone)]
243struct Timeout { 248struct Timeout {
244 #[cfg(feature = "time")] 249 #[cfg(feature = "time")]
@@ -347,7 +352,7 @@ foreach_peripheral!(
347 }; 352 };
348); 353);
349 354
350impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> { 355impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M, IM> {
351 type Error = Error; 356 type Error = Error;
352 357
353 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 358 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
@@ -355,7 +360,7 @@ impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, M> {
355 } 360 }
356} 361}
357 362
358impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> { 363impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M, IM> {
359 type Error = Error; 364 type Error = Error;
360 365
361 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { 366 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
@@ -363,7 +368,7 @@ impl<'d, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, M> {
363 } 368 }
364} 369}
365 370
366impl<'d, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M> { 371impl<'d, M: Mode, IM: MasterMode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, M, IM> {
367 type Error = Error; 372 type Error = Error;
368 373
369 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { 374 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@@ -387,11 +392,11 @@ impl embedded_hal_1::i2c::Error for Error {
387 } 392 }
388} 393}
389 394
390impl<'d, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, M> { 395impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::ErrorType for I2c<'d, M, IM> {
391 type Error = Error; 396 type Error = Error;
392} 397}
393 398
394impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> { 399impl<'d, M: Mode, IM: MasterMode> embedded_hal_1::i2c::I2c for I2c<'d, M, IM> {
395 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 400 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
396 self.blocking_read(address, read) 401 self.blocking_read(address, read)
397 } 402 }
@@ -413,7 +418,7 @@ impl<'d, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, M> {
413 } 418 }
414} 419}
415 420
416impl<'d> embedded_hal_async::i2c::I2c for I2c<'d, Async> { 421impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> {
417 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 422 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
418 self.read(address, read).await 423 self.read(address, read).await
419 } 424 }
@@ -529,9 +534,7 @@ fn operation_frames<'a, 'b: 'a>(
529 let mut next_first_frame = true; 534 let mut next_first_frame = true;
530 535
531 Ok(iter::from_fn(move || { 536 Ok(iter::from_fn(move || {
532 let Some(op) = operations.next() else { 537 let op = operations.next()?;
533 return None;
534 };
535 538
536 // Is `op` first frame of its type? 539 // Is `op` first frame of its type?
537 let first_frame = next_first_frame; 540 let first_frame = next_first_frame;
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 28026f83c..35f13ab46 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -11,6 +11,7 @@ use embassy_embedded_hal::SetConfig;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_hal_internal::drop::OnDrop; 12use embassy_hal_internal::drop::OnDrop;
13use embedded_hal_1::i2c::Operation; 13use embedded_hal_1::i2c::Operation;
14use mode::Master;
14 15
15use super::*; 16use super::*;
16use crate::mode::Mode as PeriMode; 17use crate::mode::Mode as PeriMode;
@@ -41,7 +42,7 @@ pub unsafe fn on_interrupt<T: Instance>() {
41 }); 42 });
42} 43}
43 44
44impl<'d, M: PeriMode> I2c<'d, M> { 45impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 46 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
46 self.info.regs.cr1().modify(|reg| { 47 self.info.regs.cr1().modify(|reg| {
47 reg.set_pe(false); 48 reg.set_pe(false);
@@ -354,7 +355,7 @@ impl<'d, M: PeriMode> I2c<'d, M> {
354 } 355 }
355} 356}
356 357
357impl<'d> I2c<'d, Async> { 358impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
358 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { 359 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
359 self.info.regs.cr2().modify(|w| { 360 self.info.regs.cr2().modify(|w| {
360 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 361 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
@@ -800,7 +801,7 @@ impl Timings {
800 } 801 }
801} 802}
802 803
803impl<'d, M: PeriMode> SetConfig for I2c<'d, M> { 804impl<'d, M: PeriMode> SetConfig for I2c<'d, M, Master> {
804 type Config = Hertz; 805 type Config = Hertz;
805 type ConfigError = (); 806 type ConfigError = ();
806 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 807 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 50a25754e..e24cce5c6 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -2,22 +2,87 @@ use core::cmp;
2use core::future::poll_fn; 2use core::future::poll_fn;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use config::{Address, OwnAddresses, OA2};
5use embassy_embedded_hal::SetConfig; 6use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop; 7use embassy_hal_internal::drop::OnDrop;
7use embedded_hal_1::i2c::Operation; 8use embedded_hal_1::i2c::Operation;
9use mode::{Master, MultiMaster};
10use stm32_metapac::i2c::vals::{Addmode, Oamsk};
8 11
9use super::*; 12use super::*;
10use crate::pac::i2c; 13use crate::pac::i2c;
11 14
15impl From<AddrMask> for Oamsk {
16 fn from(value: AddrMask) -> Self {
17 match value {
18 AddrMask::NOMASK => Oamsk::NO_MASK,
19 AddrMask::MASK1 => Oamsk::MASK1,
20 AddrMask::MASK2 => Oamsk::MASK2,
21 AddrMask::MASK3 => Oamsk::MASK3,
22 AddrMask::MASK4 => Oamsk::MASK4,
23 AddrMask::MASK5 => Oamsk::MASK5,
24 AddrMask::MASK6 => Oamsk::MASK6,
25 AddrMask::MASK7 => Oamsk::MASK7,
26 }
27 }
28}
29
30impl Address {
31 pub(super) fn add_mode(&self) -> stm32_metapac::i2c::vals::Addmode {
32 match self {
33 Address::SevenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT7,
34 Address::TenBit(_) => stm32_metapac::i2c::vals::Addmode::BIT10,
35 }
36 }
37}
38
39enum ReceiveResult {
40 DataAvailable,
41 StopReceived,
42 NewStart,
43}
44
45fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) {
46 if isr.tcr() {
47 trace!("interrupt: tcr");
48 }
49 if isr.tc() {
50 trace!("interrupt: tc");
51 }
52 if isr.addr() {
53 trace!("interrupt: addr");
54 }
55 if isr.stopf() {
56 trace!("interrupt: stopf");
57 }
58 if isr.nackf() {
59 trace!("interrupt: nackf");
60 }
61 if isr.berr() {
62 trace!("interrupt: berr");
63 }
64 if isr.arlo() {
65 trace!("interrupt: arlo");
66 }
67 if isr.ovr() {
68 trace!("interrupt: ovr");
69 }
70}
71
12pub(crate) unsafe fn on_interrupt<T: Instance>() { 72pub(crate) unsafe fn on_interrupt<T: Instance>() {
13 let regs = T::info().regs; 73 let regs = T::info().regs;
14 let isr = regs.isr().read(); 74 let isr = regs.isr().read();
15 75
16 if isr.tcr() || isr.tc() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() { 76 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
77 debug_print_interrupts(isr);
78
17 T::state().waker.wake(); 79 T::state().waker.wake();
18 } 80 }
81
19 critical_section::with(|_| { 82 critical_section::with(|_| {
20 regs.cr1().modify(|w| { 83 regs.cr1().modify(|w| {
84 w.set_addrie(false);
85 w.set_stopie(false);
21 // The flag can only be cleared by writting to nbytes, we won't do that here 86 // The flag can only be cleared by writting to nbytes, we won't do that here
22 w.set_tcie(false); 87 w.set_tcie(false);
23 // Error flags are to be read in the routines, so we also don't clear them here 88 // Error flags are to be read in the routines, so we also don't clear them here
@@ -27,7 +92,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
27 }); 92 });
28} 93}
29 94
30impl<'d, M: Mode> I2c<'d, M> { 95impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
31 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 96 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
32 self.info.regs.cr1().modify(|reg| { 97 self.info.regs.cr1().modify(|reg| {
33 reg.set_pe(false); 98 reg.set_pe(false);
@@ -55,7 +120,7 @@ impl<'d, M: Mode> I2c<'d, M> {
55 120
56 fn master_read( 121 fn master_read(
57 info: &'static Info, 122 info: &'static Info,
58 address: u8, 123 address: Address,
59 length: usize, 124 length: usize,
60 stop: Stop, 125 stop: Stop,
61 reload: bool, 126 reload: bool,
@@ -84,8 +149,8 @@ impl<'d, M: Mode> I2c<'d, M> {
84 }; 149 };
85 150
86 info.regs.cr2().modify(|w| { 151 info.regs.cr2().modify(|w| {
87 w.set_sadd((address << 1 | 0) as u16); 152 w.set_sadd(address.addr() << 1);
88 w.set_add10(i2c::vals::Addmode::BIT7); 153 w.set_add10(address.add_mode());
89 w.set_dir(i2c::vals::Dir::READ); 154 w.set_dir(i2c::vals::Dir::READ);
90 w.set_nbytes(length as u8); 155 w.set_nbytes(length as u8);
91 w.set_start(true); 156 w.set_start(true);
@@ -98,7 +163,7 @@ impl<'d, M: Mode> I2c<'d, M> {
98 163
99 fn master_write( 164 fn master_write(
100 info: &'static Info, 165 info: &'static Info,
101 address: u8, 166 address: Address,
102 length: usize, 167 length: usize,
103 stop: Stop, 168 stop: Stop,
104 reload: bool, 169 reload: bool,
@@ -128,8 +193,8 @@ impl<'d, M: Mode> I2c<'d, M> {
128 // START bit can be set even if the bus is BUSY or 193 // START bit can be set even if the bus is BUSY or
129 // I2C is in slave mode. 194 // I2C is in slave mode.
130 info.regs.cr2().modify(|w| { 195 info.regs.cr2().modify(|w| {
131 w.set_sadd((address << 1 | 0) as u16); 196 w.set_sadd(address.addr() << 1);
132 w.set_add10(i2c::vals::Addmode::BIT7); 197 w.set_add10(address.add_mode());
133 w.set_dir(i2c::vals::Dir::WRITE); 198 w.set_dir(i2c::vals::Dir::WRITE);
134 w.set_nbytes(length as u8); 199 w.set_nbytes(length as u8);
135 w.set_start(true); 200 w.set_start(true);
@@ -140,14 +205,14 @@ impl<'d, M: Mode> I2c<'d, M> {
140 Ok(()) 205 Ok(())
141 } 206 }
142 207
143 fn master_continue(info: &'static Info, length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> { 208 fn reload(info: &'static Info, length: usize, will_reload: bool, timeout: Timeout) -> Result<(), Error> {
144 assert!(length < 256 && length > 0); 209 assert!(length < 256 && length > 0);
145 210
146 while !info.regs.isr().read().tcr() { 211 while !info.regs.isr().read().tcr() {
147 timeout.check()?; 212 timeout.check()?;
148 } 213 }
149 214
150 let reload = if reload { 215 let will_reload = if will_reload {
151 i2c::vals::Reload::NOT_COMPLETED 216 i2c::vals::Reload::NOT_COMPLETED
152 } else { 217 } else {
153 i2c::vals::Reload::COMPLETED 218 i2c::vals::Reload::COMPLETED
@@ -155,7 +220,7 @@ impl<'d, M: Mode> I2c<'d, M> {
155 220
156 info.regs.cr2().modify(|w| { 221 info.regs.cr2().modify(|w| {
157 w.set_nbytes(length as u8); 222 w.set_nbytes(length as u8);
158 w.set_reload(reload); 223 w.set_reload(will_reload);
159 }); 224 });
160 225
161 Ok(()) 226 Ok(())
@@ -163,49 +228,132 @@ impl<'d, M: Mode> I2c<'d, M> {
163 228
164 fn flush_txdr(&self) { 229 fn flush_txdr(&self) {
165 if self.info.regs.isr().read().txis() { 230 if self.info.regs.isr().read().txis() {
166 self.info.regs.txdr().write(|w| w.set_txdata(0)); 231 trace!("Flush TXDATA with zeroes");
232 self.info.regs.txdr().modify(|w| w.set_txdata(0));
167 } 233 }
168 if !self.info.regs.isr().read().txe() { 234 if !self.info.regs.isr().read().txe() {
235 trace!("Flush TXDR");
169 self.info.regs.isr().modify(|w| w.set_txe(true)) 236 self.info.regs.isr().modify(|w| w.set_txe(true))
170 } 237 }
171 } 238 }
172 239
173 fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { 240 fn error_occurred(&self, isr: &i2c::regs::Isr, timeout: Timeout) -> Result<(), Error> {
241 if isr.nackf() {
242 trace!("NACK triggered.");
243 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
244 // NACK should be followed by STOP
245 if let Ok(()) = self.wait_stop(timeout) {
246 trace!("Got STOP after NACK, clearing flag.");
247 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
248 }
249 self.flush_txdr();
250 return Err(Error::Nack);
251 } else if isr.berr() {
252 trace!("BERR triggered.");
253 self.info.regs.icr().modify(|reg| reg.set_berrcf(true));
254 self.flush_txdr();
255 return Err(Error::Bus);
256 } else if isr.arlo() {
257 trace!("ARLO triggered.");
258 self.info.regs.icr().modify(|reg| reg.set_arlocf(true));
259 self.flush_txdr();
260 return Err(Error::Arbitration);
261 } else if isr.ovr() {
262 trace!("OVR triggered.");
263 self.info.regs.icr().modify(|reg| reg.set_ovrcf(true));
264 return Err(Error::Overrun);
265 }
266 return Ok(());
267 }
268
269 fn wait_txis(&self, timeout: Timeout) -> Result<(), Error> {
270 let mut first_loop = true;
271
174 loop { 272 loop {
175 let isr = self.info.regs.isr().read(); 273 let isr = self.info.regs.isr().read();
176 if isr.txe() { 274 self.error_occurred(&isr, timeout)?;
275 if isr.txis() {
276 trace!("TXIS");
177 return Ok(()); 277 return Ok(());
178 } else if isr.berr() {
179 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
180 return Err(Error::Bus);
181 } else if isr.arlo() {
182 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
183 return Err(Error::Arbitration);
184 } else if isr.nackf() {
185 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
186 self.flush_txdr();
187 return Err(Error::Nack);
188 } 278 }
189 279
280 {
281 if first_loop {
282 trace!("Waiting for TXIS...");
283 first_loop = false;
284 }
285 }
286 timeout.check()?;
287 }
288 }
289
290 fn wait_stop_or_err(&self, timeout: Timeout) -> Result<(), Error> {
291 loop {
292 let isr = self.info.regs.isr().read();
293 self.error_occurred(&isr, timeout)?;
294 if isr.stopf() {
295 trace!("STOP triggered.");
296 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
297 return Ok(());
298 }
299 timeout.check()?;
300 }
301 }
302 fn wait_stop(&self, timeout: Timeout) -> Result<(), Error> {
303 loop {
304 let isr = self.info.regs.isr().read();
305 if isr.stopf() {
306 trace!("STOP triggered.");
307 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
308 return Ok(());
309 }
190 timeout.check()?; 310 timeout.check()?;
191 } 311 }
192 } 312 }
193 313
194 fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> { 314 fn wait_af(&self, timeout: Timeout) -> Result<(), Error> {
195 loop { 315 loop {
196 let isr = self.info.regs.isr().read(); 316 let isr = self.info.regs.isr().read();
197 if isr.rxne() { 317 if isr.nackf() {
318 trace!("AF triggered.");
319 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
198 return Ok(()); 320 return Ok(());
199 } else if isr.berr() { 321 }
200 self.info.regs.icr().write(|reg| reg.set_berrcf(true)); 322 timeout.check()?;
201 return Err(Error::Bus); 323 }
202 } else if isr.arlo() { 324 }
203 self.info.regs.icr().write(|reg| reg.set_arlocf(true)); 325
204 return Err(Error::Arbitration); 326 fn wait_rxne(&self, timeout: Timeout) -> Result<ReceiveResult, Error> {
205 } else if isr.nackf() { 327 let mut first_loop = true;
206 self.info.regs.icr().write(|reg| reg.set_nackcf(true)); 328
207 self.flush_txdr(); 329 loop {
208 return Err(Error::Nack); 330 let isr = self.info.regs.isr().read();
331 self.error_occurred(&isr, timeout)?;
332 if isr.stopf() {
333 trace!("STOP when waiting for RXNE.");
334 if self.info.regs.isr().read().rxne() {
335 trace!("Data received with STOP.");
336 return Ok(ReceiveResult::DataAvailable);
337 }
338 trace!("STOP triggered without data.");
339 return Ok(ReceiveResult::StopReceived);
340 } else if isr.rxne() {
341 trace!("RXNE.");
342 return Ok(ReceiveResult::DataAvailable);
343 } else if isr.addr() {
344 // Another addr event received, which means START was sent again
345 // which happens when accessing memory registers (common i2c interface design)
346 // e.g. master sends: START, write 1 byte (register index), START, read N bytes (until NACK)
347 // Possible to receive this flag at the same time as rxne, so check rxne first
348 trace!("START when waiting for RXNE. Ending receive loop.");
349 // Return without clearing ADDR so `listen` can catch it
350 return Ok(ReceiveResult::NewStart);
351 }
352 {
353 if first_loop {
354 trace!("Waiting for RXNE...");
355 first_loop = false;
356 }
209 } 357 }
210 358
211 timeout.check()?; 359 timeout.check()?;
@@ -215,25 +363,21 @@ impl<'d, M: Mode> I2c<'d, M> {
215 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> { 363 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
216 loop { 364 loop {
217 let isr = self.info.regs.isr().read(); 365 let isr = self.info.regs.isr().read();
366 self.error_occurred(&isr, timeout)?;
218 if isr.tc() { 367 if isr.tc() {
219 return Ok(()); 368 return Ok(());
220 } else if isr.berr() {
221 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
222 return Err(Error::Bus);
223 } else if isr.arlo() {
224 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
225 return Err(Error::Arbitration);
226 } else if isr.nackf() {
227 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
228 self.flush_txdr();
229 return Err(Error::Nack);
230 } 369 }
231
232 timeout.check()?; 370 timeout.check()?;
233 } 371 }
234 } 372 }
235 373
236 fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> { 374 fn read_internal(
375 &mut self,
376 address: Address,
377 read: &mut [u8],
378 restart: bool,
379 timeout: Timeout,
380 ) -> Result<(), Error> {
237 let completed_chunks = read.len() / 255; 381 let completed_chunks = read.len() / 255;
238 let total_chunks = if completed_chunks * 255 == read.len() { 382 let total_chunks = if completed_chunks * 255 == read.len() {
239 completed_chunks 383 completed_chunks
@@ -254,7 +398,7 @@ impl<'d, M: Mode> I2c<'d, M> {
254 398
255 for (number, chunk) in read.chunks_mut(255).enumerate() { 399 for (number, chunk) in read.chunks_mut(255).enumerate() {
256 if number != 0 { 400 if number != 0 {
257 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 401 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
258 } 402 }
259 403
260 for byte in chunk { 404 for byte in chunk {
@@ -267,7 +411,13 @@ impl<'d, M: Mode> I2c<'d, M> {
267 Ok(()) 411 Ok(())
268 } 412 }
269 413
270 fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> { 414 fn write_internal(
415 &mut self,
416 address: Address,
417 write: &[u8],
418 send_stop: bool,
419 timeout: Timeout,
420 ) -> Result<(), Error> {
271 let completed_chunks = write.len() / 255; 421 let completed_chunks = write.len() / 255;
272 let total_chunks = if completed_chunks * 255 == write.len() { 422 let total_chunks = if completed_chunks * 255 == write.len() {
273 completed_chunks 423 completed_chunks
@@ -295,14 +445,14 @@ impl<'d, M: Mode> I2c<'d, M> {
295 445
296 for (number, chunk) in write.chunks(255).enumerate() { 446 for (number, chunk) in write.chunks(255).enumerate() {
297 if number != 0 { 447 if number != 0 {
298 Self::master_continue(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 448 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
299 } 449 }
300 450
301 for byte in chunk { 451 for byte in chunk {
302 // Wait until we are allowed to send data 452 // Wait until we are allowed to send data
303 // (START has been ACKed or last byte when 453 // (START has been ACKed or last byte when
304 // through) 454 // through)
305 if let Err(err) = self.wait_txe(timeout) { 455 if let Err(err) = self.wait_txis(timeout) {
306 if send_stop { 456 if send_stop {
307 self.master_stop(); 457 self.master_stop();
308 } 458 }
@@ -325,20 +475,20 @@ impl<'d, M: Mode> I2c<'d, M> {
325 475
326 /// Blocking read. 476 /// Blocking read.
327 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 477 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
328 self.read_internal(address, read, false, self.timeout()) 478 self.read_internal(address.into(), read, false, self.timeout())
329 // Automatic Stop 479 // Automatic Stop
330 } 480 }
331 481
332 /// Blocking write. 482 /// Blocking write.
333 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 483 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
334 self.write_internal(address, write, true, self.timeout()) 484 self.write_internal(address.into(), write, true, self.timeout())
335 } 485 }
336 486
337 /// Blocking write, restart, read. 487 /// Blocking write, restart, read.
338 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 488 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
339 let timeout = self.timeout(); 489 let timeout = self.timeout();
340 self.write_internal(address, write, false, timeout)?; 490 self.write_internal(address.into(), write, false, timeout)?;
341 self.read_internal(address, read, true, timeout) 491 self.read_internal(address.into(), read, true, timeout)
342 // Automatic Stop 492 // Automatic Stop
343 } 493 }
344 494
@@ -368,7 +518,7 @@ impl<'d, M: Mode> I2c<'d, M> {
368 518
369 if let Err(err) = Self::master_write( 519 if let Err(err) = Self::master_write(
370 self.info, 520 self.info,
371 address, 521 address.into(),
372 first_length.min(255), 522 first_length.min(255),
373 Stop::Software, 523 Stop::Software,
374 (first_length > 255) || (last_slice_index != 0), 524 (first_length > 255) || (last_slice_index != 0),
@@ -389,7 +539,7 @@ impl<'d, M: Mode> I2c<'d, M> {
389 let last_chunk_idx = total_chunks.saturating_sub(1); 539 let last_chunk_idx = total_chunks.saturating_sub(1);
390 540
391 if idx != 0 { 541 if idx != 0 {
392 if let Err(err) = Self::master_continue( 542 if let Err(err) = Self::reload(
393 self.info, 543 self.info,
394 slice_len.min(255), 544 slice_len.min(255),
395 (idx != last_slice_index) || (slice_len > 255), 545 (idx != last_slice_index) || (slice_len > 255),
@@ -402,7 +552,7 @@ impl<'d, M: Mode> I2c<'d, M> {
402 552
403 for (number, chunk) in slice.chunks(255).enumerate() { 553 for (number, chunk) in slice.chunks(255).enumerate() {
404 if number != 0 { 554 if number != 0 {
405 if let Err(err) = Self::master_continue( 555 if let Err(err) = Self::reload(
406 self.info, 556 self.info,
407 chunk.len(), 557 chunk.len(),
408 (number != last_chunk_idx) || (idx != last_slice_index), 558 (number != last_chunk_idx) || (idx != last_slice_index),
@@ -417,7 +567,7 @@ impl<'d, M: Mode> I2c<'d, M> {
417 // Wait until we are allowed to send data 567 // Wait until we are allowed to send data
418 // (START has been ACKed or last byte when 568 // (START has been ACKed or last byte when
419 // through) 569 // through)
420 if let Err(err) = self.wait_txe(timeout) { 570 if let Err(err) = self.wait_txis(timeout) {
421 self.master_stop(); 571 self.master_stop();
422 return Err(err); 572 return Err(err);
423 } 573 }
@@ -435,10 +585,10 @@ impl<'d, M: Mode> I2c<'d, M> {
435 } 585 }
436} 586}
437 587
438impl<'d> I2c<'d, Async> { 588impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
439 async fn write_dma_internal( 589 async fn write_dma_internal(
440 &mut self, 590 &mut self,
441 address: u8, 591 address: Address,
442 write: &[u8], 592 write: &[u8],
443 first_slice: bool, 593 first_slice: bool,
444 last_slice: bool, 594 last_slice: bool,
@@ -512,7 +662,7 @@ impl<'d> I2c<'d, Async> {
512 timeout, 662 timeout,
513 )?; 663 )?;
514 } else { 664 } else {
515 Self::master_continue(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?; 665 Self::reload(self.info, total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
516 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 666 self.info.regs.cr1().modify(|w| w.set_tcie(true));
517 } 667 }
518 } else if !(isr.tcr() || isr.tc()) { 668 } else if !(isr.tcr() || isr.tc()) {
@@ -523,7 +673,7 @@ impl<'d> I2c<'d, Async> {
523 } else { 673 } else {
524 let last_piece = (remaining_len <= 255) && last_slice; 674 let last_piece = (remaining_len <= 255) && last_slice;
525 675
526 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { 676 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) {
527 return Poll::Ready(Err(e)); 677 return Poll::Ready(Err(e));
528 } 678 }
529 self.info.regs.cr1().modify(|w| w.set_tcie(true)); 679 self.info.regs.cr1().modify(|w| w.set_tcie(true));
@@ -551,7 +701,7 @@ impl<'d> I2c<'d, Async> {
551 701
552 async fn read_dma_internal( 702 async fn read_dma_internal(
553 &mut self, 703 &mut self,
554 address: u8, 704 address: Address,
555 buffer: &mut [u8], 705 buffer: &mut [u8],
556 restart: bool, 706 restart: bool,
557 timeout: Timeout, 707 timeout: Timeout,
@@ -626,7 +776,7 @@ impl<'d> I2c<'d, Async> {
626 } else { 776 } else {
627 let last_piece = remaining_len <= 255; 777 let last_piece = remaining_len <= 255;
628 778
629 if let Err(e) = Self::master_continue(self.info, remaining_len.min(255), !last_piece, timeout) { 779 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !last_piece, timeout) {
630 return Poll::Ready(Err(e)); 780 return Poll::Ready(Err(e));
631 } 781 }
632 // Return here if we are on last chunk, 782 // Return here if we are on last chunk,
@@ -647,7 +797,6 @@ impl<'d> I2c<'d, Async> {
647 797
648 Ok(()) 798 Ok(())
649 } 799 }
650
651 // ========================= 800 // =========================
652 // Async public API 801 // Async public API
653 802
@@ -655,10 +804,10 @@ impl<'d> I2c<'d, Async> {
655 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 804 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
656 let timeout = self.timeout(); 805 let timeout = self.timeout();
657 if write.is_empty() { 806 if write.is_empty() {
658 self.write_internal(address, write, true, timeout) 807 self.write_internal(address.into(), write, true, timeout)
659 } else { 808 } else {
660 timeout 809 timeout
661 .with(self.write_dma_internal(address, write, true, true, true, timeout)) 810 .with(self.write_dma_internal(address.into(), write, true, true, true, timeout))
662 .await 811 .await
663 } 812 }
664 } 813 }
@@ -666,7 +815,7 @@ impl<'d> I2c<'d, Async> {
666 /// Write multiple buffers. 815 /// Write multiple buffers.
667 /// 816 ///
668 /// The buffers are concatenated in a single write transaction. 817 /// The buffers are concatenated in a single write transaction.
669 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { 818 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> {
670 let timeout = self.timeout(); 819 let timeout = self.timeout();
671 820
672 if write.is_empty() { 821 if write.is_empty() {
@@ -693,9 +842,9 @@ impl<'d> I2c<'d, Async> {
693 let timeout = self.timeout(); 842 let timeout = self.timeout();
694 843
695 if buffer.is_empty() { 844 if buffer.is_empty() {
696 self.read_internal(address, buffer, false, timeout) 845 self.read_internal(address.into(), buffer, false, timeout)
697 } else { 846 } else {
698 let fut = self.read_dma_internal(address, buffer, false, timeout); 847 let fut = self.read_dma_internal(address.into(), buffer, false, timeout);
699 timeout.with(fut).await 848 timeout.with(fut).await
700 } 849 }
701 } 850 }
@@ -705,16 +854,16 @@ impl<'d> I2c<'d, Async> {
705 let timeout = self.timeout(); 854 let timeout = self.timeout();
706 855
707 if write.is_empty() { 856 if write.is_empty() {
708 self.write_internal(address, write, false, timeout)?; 857 self.write_internal(address.into(), write, false, timeout)?;
709 } else { 858 } else {
710 let fut = self.write_dma_internal(address, write, true, true, false, timeout); 859 let fut = self.write_dma_internal(address.into(), write, true, true, false, timeout);
711 timeout.with(fut).await?; 860 timeout.with(fut).await?;
712 } 861 }
713 862
714 if read.is_empty() { 863 if read.is_empty() {
715 self.read_internal(address, read, true, timeout)?; 864 self.read_internal(address.into(), read, true, timeout)?;
716 } else { 865 } else {
717 let fut = self.read_dma_internal(address, read, true, timeout); 866 let fut = self.read_dma_internal(address.into(), read, true, timeout);
718 timeout.with(fut).await?; 867 timeout.with(fut).await?;
719 } 868 }
720 869
@@ -733,6 +882,414 @@ impl<'d> I2c<'d, Async> {
733 } 882 }
734} 883}
735 884
885impl<'d, M: Mode> I2c<'d, M, Master> {
886 /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster)
887 pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> {
888 let mut slave = I2c {
889 info: self.info,
890 state: self.state,
891 kernel_clock: self.kernel_clock,
892 tx_dma: self.tx_dma.take(),
893 rx_dma: self.rx_dma.take(),
894 #[cfg(feature = "time")]
895 timeout: self.timeout,
896 _phantom: PhantomData,
897 _phantom2: PhantomData,
898 _drop_guard: self._drop_guard,
899 };
900 slave.init_slave(slave_addr_config);
901 slave
902 }
903}
904
905impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
906 pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) {
907 self.info.regs.cr1().modify(|reg| {
908 reg.set_pe(false);
909 });
910
911 self.info.regs.cr1().modify(|reg| {
912 reg.set_nostretch(false);
913 reg.set_gcen(config.general_call);
914 reg.set_sbc(true);
915 reg.set_pe(true);
916 });
917
918 self.reconfigure_addresses(config.addr);
919 }
920
921 /// Configure the slave address.
922 pub fn reconfigure_addresses(&mut self, addresses: OwnAddresses) {
923 match addresses {
924 OwnAddresses::OA1(oa1) => self.configure_oa1(oa1),
925 OwnAddresses::OA2(oa2) => self.configure_oa2(oa2),
926 OwnAddresses::Both { oa1, oa2 } => {
927 self.configure_oa1(oa1);
928 self.configure_oa2(oa2);
929 }
930 }
931 }
932
933 fn configure_oa1(&mut self, oa1: Address) {
934 match oa1 {
935 Address::SevenBit(addr) => self.info.regs.oar1().write(|reg| {
936 reg.set_oa1en(false);
937 reg.set_oa1((addr << 1) as u16);
938 reg.set_oa1mode(Addmode::BIT7);
939 reg.set_oa1en(true);
940 }),
941 Address::TenBit(addr) => self.info.regs.oar1().write(|reg| {
942 reg.set_oa1en(false);
943 reg.set_oa1(addr);
944 reg.set_oa1mode(Addmode::BIT10);
945 reg.set_oa1en(true);
946 }),
947 }
948 }
949
950 fn configure_oa2(&mut self, oa2: OA2) {
951 self.info.regs.oar2().write(|reg| {
952 reg.set_oa2en(false);
953 reg.set_oa2msk(oa2.mask.into());
954 reg.set_oa2(oa2.addr << 1);
955 reg.set_oa2en(true);
956 });
957 }
958
959 fn determine_matched_address(&self) -> Result<Address, Error> {
960 let matched = self.info.regs.isr().read().addcode();
961
962 if matched >> 3 == 0b11110 {
963 // is 10-bit address and we need to get the other 8 bits from the rxdr
964 // we do this by doing a blocking read of 1 byte
965 let mut buffer = [0];
966 self.slave_read_internal(&mut buffer, self.timeout())?;
967 Ok(Address::TenBit((matched as u16) << 6 | buffer[0] as u16))
968 } else {
969 Ok(Address::SevenBit(matched))
970 }
971 }
972}
973
974impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
975 /// # Safety
976 /// This function will clear the address flag which will stop the clock stretching.
977 /// This should only be done after the dma transfer has been set up.
978 fn slave_start(info: &'static Info, length: usize, reload: bool) {
979 assert!(length < 256);
980
981 let reload = if reload {
982 i2c::vals::Reload::NOT_COMPLETED
983 } else {
984 i2c::vals::Reload::COMPLETED
985 };
986
987 info.regs.cr2().modify(|w| {
988 w.set_nbytes(length as u8);
989 w.set_reload(reload);
990 });
991
992 // clear the address flag, will stop the clock stretching.
993 // this should only be done after the dma transfer has been set up.
994 info.regs.icr().modify(|reg| reg.set_addrcf(true));
995 trace!("ADDRCF cleared (ADDR interrupt enabled, clock stretching ended)");
996 }
997
998 // A blocking read operation
999 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
1000 let completed_chunks = read.len() / 255;
1001 let total_chunks = if completed_chunks * 255 == read.len() {
1002 completed_chunks
1003 } else {
1004 completed_chunks + 1
1005 };
1006 let last_chunk_idx = total_chunks.saturating_sub(1);
1007 let total_len = read.len();
1008 let mut remaining_len = total_len;
1009
1010 for (number, chunk) in read.chunks_mut(255).enumerate() {
1011 trace!(
1012 "--- Slave RX transmission start - chunk: {}, expected (max) size: {}",
1013 number,
1014 chunk.len()
1015 );
1016 if number == 0 {
1017 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1018 } else {
1019 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
1020 }
1021
1022 let mut index = 0;
1023
1024 for byte in chunk {
1025 // Wait until we have received something
1026 match self.wait_rxne(timeout) {
1027 Ok(ReceiveResult::StopReceived) | Ok(ReceiveResult::NewStart) => {
1028 trace!("--- Slave RX transmission end (early)");
1029 return Ok(total_len - remaining_len); // Return N bytes read
1030 }
1031 Ok(ReceiveResult::DataAvailable) => {
1032 *byte = self.info.regs.rxdr().read().rxdata();
1033 remaining_len = remaining_len.saturating_sub(1);
1034 {
1035 trace!("Slave RX data {}: {:#04x}", index, byte);
1036 index = index + 1;
1037 }
1038 }
1039 Err(e) => return Err(e),
1040 };
1041 }
1042 }
1043 self.wait_stop_or_err(timeout)?;
1044
1045 trace!("--- Slave RX transmission end");
1046 Ok(total_len - remaining_len) // Return N bytes read
1047 }
1048
1049 // A blocking write operation
1050 fn slave_write_internal(&mut self, write: &[u8], timeout: Timeout) -> Result<(), Error> {
1051 let completed_chunks = write.len() / 255;
1052 let total_chunks = if completed_chunks * 255 == write.len() {
1053 completed_chunks
1054 } else {
1055 completed_chunks + 1
1056 };
1057 let last_chunk_idx = total_chunks.saturating_sub(1);
1058
1059 for (number, chunk) in write.chunks(255).enumerate() {
1060 trace!(
1061 "--- Slave TX transmission start - chunk: {}, size: {}",
1062 number,
1063 chunk.len()
1064 );
1065 if number == 0 {
1066 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1067 } else {
1068 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
1069 }
1070
1071 let mut index = 0;
1072
1073 for byte in chunk {
1074 // Wait until we are allowed to send data
1075 // (START has been ACKed or last byte when through)
1076 self.wait_txis(timeout)?;
1077
1078 {
1079 trace!("Slave TX data {}: {:#04x}", index, byte);
1080 index = index + 1;
1081 }
1082 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
1083 }
1084 }
1085 self.wait_af(timeout)?;
1086 self.flush_txdr();
1087 self.wait_stop_or_err(timeout)?;
1088
1089 trace!("--- Slave TX transmission end");
1090 Ok(())
1091 }
1092
1093 /// Listen for incoming I2C messages.
1094 ///
1095 /// The listen method is an asynchronous method but it does not require DMA to be asynchronous.
1096 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1097 let state = self.state;
1098 self.info.regs.cr1().modify(|reg| {
1099 reg.set_addrie(true);
1100 trace!("Enable ADDRIE");
1101 });
1102
1103 poll_fn(|cx| {
1104 state.waker.register(cx.waker());
1105 let isr = self.info.regs.isr().read();
1106 if !isr.addr() {
1107 Poll::Pending
1108 } else {
1109 trace!("ADDR triggered (address match)");
1110 // we do not clear the address flag here as it will be cleared by the dma read/write
1111 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
1112 match isr.dir() {
1113 i2c::vals::Dir::WRITE => {
1114 trace!("DIR: write");
1115 Poll::Ready(Ok(SlaveCommand {
1116 kind: SlaveCommandKind::Write,
1117 address: self.determine_matched_address()?,
1118 }))
1119 }
1120 i2c::vals::Dir::READ => {
1121 trace!("DIR: read");
1122 Poll::Ready(Ok(SlaveCommand {
1123 kind: SlaveCommandKind::Read,
1124 address: self.determine_matched_address()?,
1125 }))
1126 }
1127 }
1128 }
1129 })
1130 .await
1131 }
1132
1133 /// Respond to a write command.
1134 ///
1135 /// Returns total number of bytes received.
1136 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<usize, Error> {
1137 let timeout = self.timeout();
1138 self.slave_read_internal(read, timeout)
1139 }
1140
1141 /// Respond to a read command.
1142 pub fn blocking_respond_to_read(&mut self, write: &[u8]) -> Result<(), Error> {
1143 let timeout = self.timeout();
1144 self.slave_write_internal(write, timeout)
1145 }
1146}
1147
1148impl<'d> I2c<'d, Async, MultiMaster> {
1149 /// Respond to a write command.
1150 ///
1151 /// Returns the total number of bytes received.
1152 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1153 let timeout = self.timeout();
1154 timeout.with(self.read_dma_internal_slave(buffer, timeout)).await
1155 }
1156
1157 /// Respond to a read request from an I2C master.
1158 pub async fn respond_to_read(&mut self, write: &[u8]) -> Result<SendStatus, Error> {
1159 let timeout = self.timeout();
1160 timeout.with(self.write_dma_internal_slave(write, timeout)).await
1161 }
1162
1163 // for data reception in slave mode
1164 //
1165 // returns the total number of bytes received
1166 async fn read_dma_internal_slave(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
1167 let total_len = buffer.len();
1168 let mut remaining_len = total_len;
1169
1170 let regs = self.info.regs;
1171
1172 let dma_transfer = unsafe {
1173 regs.cr1().modify(|w| {
1174 w.set_rxdmaen(true);
1175 w.set_stopie(true);
1176 w.set_tcie(true);
1177 });
1178 let src = regs.rxdr().as_ptr() as *mut u8;
1179
1180 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1181 };
1182
1183 let state = self.state;
1184
1185 let on_drop = OnDrop::new(|| {
1186 regs.cr1().modify(|w| {
1187 w.set_rxdmaen(false);
1188 w.set_stopie(false);
1189 w.set_tcie(false);
1190 });
1191 });
1192
1193 let total_received = poll_fn(|cx| {
1194 state.waker.register(cx.waker());
1195
1196 let isr = regs.isr().read();
1197
1198 if remaining_len == total_len {
1199 Self::slave_start(self.info, total_len.min(255), total_len > 255);
1200 remaining_len = remaining_len.saturating_sub(255);
1201 Poll::Pending
1202 } else if isr.tcr() {
1203 let is_last_slice = remaining_len <= 255;
1204 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) {
1205 return Poll::Ready(Err(e));
1206 }
1207 remaining_len = remaining_len.saturating_sub(255);
1208 regs.cr1().modify(|w| w.set_tcie(true));
1209 Poll::Pending
1210 } else if isr.stopf() {
1211 regs.icr().write(|reg| reg.set_stopcf(true));
1212 let poll = Poll::Ready(Ok(total_len - remaining_len));
1213 poll
1214 } else {
1215 Poll::Pending
1216 }
1217 })
1218 .await?;
1219
1220 dma_transfer.await;
1221
1222 drop(on_drop);
1223
1224 Ok(total_received)
1225 }
1226
1227 async fn write_dma_internal_slave(&mut self, buffer: &[u8], timeout: Timeout) -> Result<SendStatus, Error> {
1228 let total_len = buffer.len();
1229 let mut remaining_len = total_len;
1230
1231 let mut dma_transfer = unsafe {
1232 let regs = self.info.regs;
1233 regs.cr1().modify(|w| {
1234 w.set_txdmaen(true);
1235 w.set_stopie(true);
1236 w.set_tcie(true);
1237 });
1238 let dst = regs.txdr().as_ptr() as *mut u8;
1239
1240 self.tx_dma.as_mut().unwrap().write(buffer, dst, Default::default())
1241 };
1242
1243 let on_drop = OnDrop::new(|| {
1244 let regs = self.info.regs;
1245 regs.cr1().modify(|w| {
1246 w.set_txdmaen(false);
1247 w.set_stopie(false);
1248 w.set_tcie(false);
1249 })
1250 });
1251
1252 let state = self.state;
1253
1254 let size = poll_fn(|cx| {
1255 state.waker.register(cx.waker());
1256
1257 let isr = self.info.regs.isr().read();
1258
1259 if remaining_len == total_len {
1260 Self::slave_start(self.info, total_len.min(255), total_len > 255);
1261 remaining_len = remaining_len.saturating_sub(255);
1262 Poll::Pending
1263 } else if isr.tcr() {
1264 let is_last_slice = remaining_len <= 255;
1265 if let Err(e) = Self::reload(self.info, remaining_len.min(255), !is_last_slice, timeout) {
1266 return Poll::Ready(Err(e));
1267 }
1268 remaining_len = remaining_len.saturating_sub(255);
1269 self.info.regs.cr1().modify(|w| w.set_tcie(true));
1270 Poll::Pending
1271 } else if isr.stopf() {
1272 self.info.regs.icr().write(|reg| reg.set_stopcf(true));
1273 if remaining_len > 0 {
1274 dma_transfer.request_stop();
1275 Poll::Ready(Ok(SendStatus::LeftoverBytes(remaining_len as usize)))
1276 } else {
1277 Poll::Ready(Ok(SendStatus::Done))
1278 }
1279 } else {
1280 Poll::Pending
1281 }
1282 })
1283 .await?;
1284
1285 dma_transfer.await;
1286
1287 drop(on_drop);
1288
1289 Ok(size)
1290 }
1291}
1292
736/// I2C Stop Configuration 1293/// I2C Stop Configuration
737/// 1294///
738/// Peripheral options for generating the STOP condition 1295/// Peripheral options for generating the STOP condition
@@ -857,7 +1414,7 @@ impl Timings {
857 } 1414 }
858} 1415}
859 1416
860impl<'d, M: Mode> SetConfig for I2c<'d, M> { 1417impl<'d, M: Mode> SetConfig for I2c<'d, M, Master> {
861 type Config = Hertz; 1418 type Config = Hertz;
862 type ConfigError = (); 1419 type ConfigError = ();
863 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 1420 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
@@ -882,3 +1439,21 @@ impl<'d, M: Mode> SetConfig for I2c<'d, M> {
882 Ok(()) 1439 Ok(())
883 } 1440 }
884} 1441}
1442
1443impl<'d, M: Mode> SetConfig for I2c<'d, M, MultiMaster> {
1444 type Config = (Hertz, SlaveAddrConfig);
1445 type ConfigError = ();
1446 fn set_config(&mut self, (config, addr_config): &Self::Config) -> Result<(), ()> {
1447 let timings = Timings::new(self.kernel_clock, *config);
1448 self.info.regs.timingr().write(|reg| {
1449 reg.set_presc(timings.prescale);
1450 reg.set_scll(timings.scll);
1451 reg.set_sclh(timings.sclh);
1452 reg.set_sdadel(timings.sdadel);
1453 reg.set_scldel(timings.scldel);
1454 });
1455 self.init_slave(*addr_config);
1456
1457 Ok(())
1458 }
1459}
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 20cd20dca..670d8332c 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -104,9 +104,6 @@ impl Ipcc {
104 rcc::enable_and_reset::<IPCC>(); 104 rcc::enable_and_reset::<IPCC>();
105 IPCC::set_cpu2(true); 105 IPCC::set_cpu2(true);
106 106
107 // set RF wake-up clock = LSE
108 crate::pac::RCC.csr().modify(|w| w.set_rfwkpsel(0b01));
109
110 let regs = IPCC::regs(); 107 let regs = IPCC::regs();
111 108
112 regs.cpu(0).cr().modify(|w| { 109 regs.cpu(0).cr().modify(|w| {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 973acc9bb..c7a33ed72 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -178,7 +178,7 @@ pub use crate::_generated::interrupt;
178macro_rules! bind_interrupts { 178macro_rules! bind_interrupts {
179 ($(#[$outer:meta])* $vis:vis struct $name:ident { 179 ($(#[$outer:meta])* $vis:vis struct $name:ident {
180 $( 180 $(
181 $(#[$inner:meta])* 181 $(#[doc = $doc:literal])*
182 $(#[cfg($cond_irq:meta)])? 182 $(#[cfg($cond_irq:meta)])?
183 $irq:ident => $( 183 $irq:ident => $(
184 $(#[cfg($cond_handler:meta)])? 184 $(#[cfg($cond_handler:meta)])?
@@ -194,13 +194,15 @@ macro_rules! bind_interrupts {
194 #[allow(non_snake_case)] 194 #[allow(non_snake_case)]
195 #[no_mangle] 195 #[no_mangle]
196 $(#[cfg($cond_irq)])? 196 $(#[cfg($cond_irq)])?
197 $(#[$inner])* 197 $(#[doc = $doc])*
198 unsafe extern "C" fn $irq() { 198 unsafe extern "C" fn $irq() {
199 $( 199 unsafe {
200 $(#[cfg($cond_handler)])? 200 $(
201 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); 201 $(#[cfg($cond_handler)])?
202 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
202 203
203 )* 204 )*
205 }
204 } 206 }
205 207
206 $(#[cfg($cond_irq)])? 208 $(#[cfg($cond_irq)])?
@@ -242,12 +244,12 @@ pub struct Config {
242 #[cfg(dbgmcu)] 244 #[cfg(dbgmcu)]
243 pub enable_debug_during_sleep: bool, 245 pub enable_debug_during_sleep: bool,
244 246
245 /// On low-power boards (eg. `stm32l4`, `stm32l5` and `stm32u5`), 247 /// On low-power boards (eg. `stm32l4`, `stm32l5`, `stm32wba` and `stm32u5`),
246 /// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`), 248 /// some GPIO pins are powered by an auxiliary, independent power supply (`VDDIO2`),
247 /// which needs to be enabled before these pins can be used. 249 /// which needs to be enabled before these pins can be used.
248 /// 250 ///
249 /// May increase power consumption. Defaults to true. 251 /// May increase power consumption. Defaults to true.
250 #[cfg(any(stm32l4, stm32l5, stm32u5))] 252 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
251 pub enable_independent_io_supply: bool, 253 pub enable_independent_io_supply: bool,
252 254
253 /// On the U5 series all analog peripherals are powered by a separate supply. 255 /// On the U5 series all analog peripherals are powered by a separate supply.
@@ -291,7 +293,7 @@ impl Default for Config {
291 rcc: Default::default(), 293 rcc: Default::default(),
292 #[cfg(dbgmcu)] 294 #[cfg(dbgmcu)]
293 enable_debug_during_sleep: true, 295 enable_debug_during_sleep: true,
294 #[cfg(any(stm32l4, stm32l5, stm32u5))] 296 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
295 enable_independent_io_supply: true, 297 enable_independent_io_supply: true,
296 #[cfg(stm32u5)] 298 #[cfg(stm32u5)]
297 enable_independent_analog_supply: true, 299 enable_independent_analog_supply: true,
@@ -540,6 +542,13 @@ fn init_hw(config: Config) -> Peripherals {
540 w.set_iosv(config.enable_independent_io_supply); 542 w.set_iosv(config.enable_independent_io_supply);
541 }); 543 });
542 } 544 }
545 #[cfg(stm32wba)]
546 {
547 use crate::pac::pwr::vals;
548 crate::pac::PWR.svmcr().modify(|w| {
549 w.set_io2sv(vals::Io2sv::B_0X1);
550 });
551 }
543 #[cfg(stm32u5)] 552 #[cfg(stm32u5)]
544 { 553 {
545 crate::pac::PWR.svmcr().modify(|w| { 554 crate::pac::PWR.svmcr().modify(|w| {
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 7734365f1..d13df5a6b 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -124,15 +124,18 @@ pub enum StopMode {
124 Stop2, 124 Stop2,
125} 125}
126 126
127#[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] 127#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))]
128use stm32_metapac::pwr::vals::Lpms; 128use stm32_metapac::pwr::vals::Lpms;
129 129
130#[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] 130#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))]
131impl Into<Lpms> for StopMode { 131impl Into<Lpms> for StopMode {
132 fn into(self) -> Lpms { 132 fn into(self) -> Lpms {
133 match self { 133 match self {
134 StopMode::Stop1 => Lpms::STOP1, 134 StopMode::Stop1 => Lpms::STOP1,
135 #[cfg(not(stm32wba))]
135 StopMode::Stop2 => Lpms::STOP2, 136 StopMode::Stop2 => Lpms::STOP2,
137 #[cfg(stm32wba)]
138 StopMode::Stop2 => Lpms::STOP1, // TODO: WBA has no STOP2?
136 } 139 }
137 } 140 }
138} 141}
@@ -198,7 +201,7 @@ impl Executor {
198 201
199 #[allow(unused_variables)] 202 #[allow(unused_variables)]
200 fn configure_stop(&mut self, stop_mode: StopMode) { 203 fn configure_stop(&mut self, stop_mode: StopMode) {
201 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0))] 204 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0, stm32wba))]
202 crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into())); 205 crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into()));
203 #[cfg(stm32h5)] 206 #[cfg(stm32h5)]
204 crate::pac::PWR.pmcr().modify(|v| { 207 crate::pac::PWR.pmcr().modify(|v| {
diff --git a/embassy-stm32/src/lptim/timer/mod.rs b/embassy-stm32/src/lptim/timer/mod.rs
index a629be62b..648da5940 100644
--- a/embassy-stm32/src/lptim/timer/mod.rs
+++ b/embassy-stm32/src/lptim/timer/mod.rs
@@ -115,6 +115,31 @@ impl<'d, T: Instance> Timer<'d, T> {
115 .ccmr(0) 115 .ccmr(0)
116 .modify(|w| w.set_ccsel(channel.index(), direction.into())); 116 .modify(|w| w.set_ccsel(channel.index(), direction.into()));
117 } 117 }
118
119 /// Enable the timer interrupt.
120 pub fn enable_interrupt(&self) {
121 T::regs().dier().modify(|w| w.set_arrmie(true));
122 }
123
124 /// Disable the timer interrupt.
125 pub fn disable_interrupt(&self) {
126 T::regs().dier().modify(|w| w.set_arrmie(false));
127 }
128
129 /// Check if the timer interrupt is enabled.
130 pub fn is_interrupt_enabled(&self) -> bool {
131 T::regs().dier().read().arrmie()
132 }
133
134 /// Check if the timer interrupt is pending.
135 pub fn is_interrupt_pending(&self) -> bool {
136 T::regs().isr().read().arrm()
137 }
138
139 /// Clear the timer interrupt.
140 pub fn clear_interrupt(&self) {
141 T::regs().icr().write(|w| w.set_arrmcf(true));
142 }
118} 143}
119 144
120#[cfg(not(any(lptim_v2a, lptim_v2b)))] 145#[cfg(not(any(lptim_v2a, lptim_v2b)))]
@@ -128,4 +153,29 @@ impl<'d, T: Instance> Timer<'d, T> {
128 pub fn get_compare_value(&self) -> u16 { 153 pub fn get_compare_value(&self) -> u16 {
129 T::regs().cmp().read().cmp() 154 T::regs().cmp().read().cmp()
130 } 155 }
156
157 /// Enable the timer interrupt.
158 pub fn enable_interrupt(&self) {
159 T::regs().ier().modify(|w| w.set_arrmie(true));
160 }
161
162 /// Disable the timer interrupt.
163 pub fn disable_interrupt(&self) {
164 T::regs().ier().modify(|w| w.set_arrmie(false));
165 }
166
167 /// Check if the timer interrupt is enabled.
168 pub fn is_interrupt_enabled(&self) -> bool {
169 T::regs().ier().read().arrmie()
170 }
171
172 /// Check if the timer interrupt is pending.
173 pub fn is_interrupt_pending(&self) -> bool {
174 T::regs().isr().read().arrm()
175 }
176
177 /// Clear the timer interrupt.
178 pub fn clear_interrupt(&self) {
179 T::regs().icr().write(|w| w.set_arrmcf(true));
180 }
131} 181}
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs
index 7526bb180..3a0b490ba 100644
--- a/embassy-stm32/src/macros.rs
+++ b/embassy-stm32/src/macros.rs
@@ -81,17 +81,28 @@ macro_rules! dma_trait {
81 /// Note: in some chips, ST calls this the "channel", and calls channels "streams". 81 /// Note: in some chips, ST calls this the "channel", and calls channels "streams".
82 /// `embassy-stm32` always uses the "channel" and "request number" names. 82 /// `embassy-stm32` always uses the "channel" and "request number" names.
83 fn request(&self) -> crate::dma::Request; 83 fn request(&self) -> crate::dma::Request;
84 #[doc = "Remap the DMA channel"]
85 fn remap(&self);
84 } 86 }
85 }; 87 };
86} 88}
87 89
88#[allow(unused)] 90#[allow(unused)]
89macro_rules! dma_trait_impl { 91macro_rules! dma_trait_impl {
90 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr) => { 92 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr, $remap:expr) => {
91 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel { 93 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel {
92 fn request(&self) -> crate::dma::Request { 94 fn request(&self) -> crate::dma::Request {
93 $request 95 $request
94 } 96 }
97
98 fn remap(&self) {
99 critical_section::with(|_| {
100 #[allow(unused_unsafe)]
101 unsafe {
102 $remap;
103 }
104 });
105 }
95 } 106 }
96 }; 107 };
97} 108}
@@ -111,6 +122,7 @@ macro_rules! new_dma_nonopt {
111macro_rules! new_dma { 122macro_rules! new_dma {
112 ($name:ident) => {{ 123 ($name:ident) => {{
113 let dma = $name; 124 let dma = $name;
125 dma.remap();
114 let request = dma.request(); 126 let request = dma.request();
115 Some(crate::dma::ChannelAndRequest { 127 Some(crate::dma::ChannelAndRequest {
116 channel: dma.into(), 128 channel: dma.into(),
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index 2eb2e61c1..e36719ef3 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -4,10 +4,12 @@
4use embassy_hal_internal::PeripheralType; 4use embassy_hal_internal::PeripheralType;
5 5
6use crate::pac::opamp::vals::*; 6use crate::pac::opamp::vals::*;
7#[cfg(not(any(stm32g4, stm32f3)))]
8use crate::rcc::RccInfo;
7use crate::Peri; 9use crate::Peri;
8 10
9/// Performs a busy-wait delay for a specified number of microseconds. 11/// Performs a busy-wait delay for a specified number of microseconds.
10#[cfg(opamp_g4)] 12#[cfg(opamp_v5)]
11fn blocking_delay_ms(ms: u32) { 13fn blocking_delay_ms(ms: u32) {
12 #[cfg(feature = "time")] 14 #[cfg(feature = "time")]
13 embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64)); 15 embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64));
@@ -23,13 +25,13 @@ pub enum OpAmpGain {
23 Mul4, 25 Mul4,
24 Mul8, 26 Mul8,
25 Mul16, 27 Mul16,
26 #[cfg(opamp_g4)] 28 #[cfg(opamp_v5)]
27 Mul32, 29 Mul32,
28 #[cfg(opamp_g4)] 30 #[cfg(opamp_v5)]
29 Mul64, 31 Mul64,
30} 32}
31 33
32#[cfg(opamp_g4)] 34#[cfg(opamp_v5)]
33enum OpAmpDifferentialPair { 35enum OpAmpDifferentialPair {
34 P, 36 P,
35 N, 37 N,
@@ -53,7 +55,7 @@ pub struct OpAmpOutput<'d, T: Instance> {
53/// OpAmp internal outputs, wired directly to ADC inputs. 55/// OpAmp internal outputs, wired directly to ADC inputs.
54/// 56///
55/// This struct can be used as an ADC input. 57/// This struct can be used as an ADC input.
56#[cfg(opamp_g4)] 58#[cfg(opamp_v5)]
57pub struct OpAmpInternalOutput<'d, T: Instance> { 59pub struct OpAmpInternalOutput<'d, T: Instance> {
58 _inner: &'d OpAmp<'d, T>, 60 _inner: &'d OpAmp<'d, T>,
59} 61}
@@ -67,8 +69,10 @@ impl<'d, T: Instance> OpAmp<'d, T> {
67 /// Create a new driver instance. 69 /// Create a new driver instance.
68 /// 70 ///
69 /// Does not enable the opamp, but does set the speed mode on some families. 71 /// Does not enable the opamp, but does set the speed mode on some families.
70 pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self { 72 pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_v5)] speed: OpAmpSpeed) -> Self {
71 #[cfg(opamp_g4)] 73 #[cfg(not(any(stm32g4, stm32f3)))]
74 T::info().rcc.enable_and_reset();
75 #[cfg(opamp_v5)]
72 T::regs().csr().modify(|w| { 76 T::regs().csr().modify(|w| {
73 w.set_opahsm(speed == OpAmpSpeed::HighSpeed); 77 w.set_opahsm(speed == OpAmpSpeed::HighSpeed);
74 }); 78 });
@@ -94,15 +98,15 @@ impl<'d, T: Instance> OpAmp<'d, T> {
94 in_pin.set_as_analog(); 98 in_pin.set_as_analog();
95 out_pin.set_as_analog(); 99 out_pin.set_as_analog();
96 100
97 #[cfg(opamp_g4)] 101 #[cfg(opamp_v5)]
98 let vm_sel = VmSel::OUTPUT; 102 let vm_sel = VmSel::OUTPUT;
99 #[cfg(not(opamp_g4))] 103 #[cfg(not(opamp_v5))]
100 let vm_sel = VmSel::from_bits(0b11); 104 let vm_sel = VmSel::from_bits(0b11);
101 105
102 T::regs().csr().modify(|w| { 106 T::regs().csr().modify(|w| {
103 w.set_vp_sel(VpSel::from_bits(in_pin.channel())); 107 w.set_vp_sel(VpSel::from_bits(in_pin.channel()));
104 w.set_vm_sel(vm_sel); 108 w.set_vm_sel(vm_sel);
105 #[cfg(opamp_g4)] 109 #[cfg(opamp_v5)]
106 w.set_opaintoen(false); 110 w.set_opaintoen(false);
107 w.set_opampen(true); 111 w.set_opampen(true);
108 }); 112 });
@@ -129,12 +133,12 @@ impl<'d, T: Instance> OpAmp<'d, T> {
129 in_pin.set_as_analog(); 133 in_pin.set_as_analog();
130 out_pin.set_as_analog(); 134 out_pin.set_as_analog();
131 135
132 #[cfg(opamp_g4)] 136 #[cfg(opamp_v5)]
133 let vm_sel = VmSel::PGA; 137 let vm_sel = VmSel::PGA;
134 #[cfg(not(opamp_g4))] 138 #[cfg(not(opamp_v5))]
135 let vm_sel = VmSel::from_bits(0b10); 139 let vm_sel = VmSel::from_bits(0b10);
136 140
137 #[cfg(opamp_g4)] 141 #[cfg(opamp_v5)]
138 let pga_gain = match gain { 142 let pga_gain = match gain {
139 OpAmpGain::Mul2 => PgaGain::GAIN2, 143 OpAmpGain::Mul2 => PgaGain::GAIN2,
140 OpAmpGain::Mul4 => PgaGain::GAIN4, 144 OpAmpGain::Mul4 => PgaGain::GAIN4,
@@ -143,7 +147,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
143 OpAmpGain::Mul32 => PgaGain::GAIN32, 147 OpAmpGain::Mul32 => PgaGain::GAIN32,
144 OpAmpGain::Mul64 => PgaGain::GAIN64, 148 OpAmpGain::Mul64 => PgaGain::GAIN64,
145 }; 149 };
146 #[cfg(not(opamp_g4))] 150 #[cfg(not(opamp_v5))]
147 let pga_gain = PgaGain::from_bits(match gain { 151 let pga_gain = PgaGain::from_bits(match gain {
148 OpAmpGain::Mul2 => 0b00, 152 OpAmpGain::Mul2 => 0b00,
149 OpAmpGain::Mul4 => 0b01, 153 OpAmpGain::Mul4 => 0b01,
@@ -155,7 +159,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
155 w.set_vp_sel(VpSel::from_bits(in_pin.channel())); 159 w.set_vp_sel(VpSel::from_bits(in_pin.channel()));
156 w.set_vm_sel(vm_sel); 160 w.set_vm_sel(vm_sel);
157 w.set_pga_gain(pga_gain); 161 w.set_pga_gain(pga_gain);
158 #[cfg(opamp_g4)] 162 #[cfg(opamp_v5)]
159 w.set_opaintoen(false); 163 w.set_opaintoen(false);
160 w.set_opampen(true); 164 w.set_opampen(true);
161 }); 165 });
@@ -170,7 +174,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
170 /// preventing it being used elsewhere. The `OpAmpOutput` can then be 174 /// preventing it being used elsewhere. The `OpAmpOutput` can then be
171 /// directly used as an ADC input. The opamp will be disabled when the 175 /// directly used as an ADC input. The opamp will be disabled when the
172 /// [`OpAmpOutput`] is dropped. 176 /// [`OpAmpOutput`] is dropped.
173 #[cfg(opamp_g4)] 177 #[cfg(opamp_v5)]
174 pub fn buffer_dac(&mut self, out_pin: Peri<'_, impl OutputPin<T> + crate::gpio::Pin>) -> OpAmpOutput<'_, T> { 178 pub fn buffer_dac(&mut self, out_pin: Peri<'_, impl OutputPin<T> + crate::gpio::Pin>) -> OpAmpOutput<'_, T> {
175 out_pin.set_as_analog(); 179 out_pin.set_as_analog();
176 180
@@ -194,7 +198,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
194 /// 198 ///
195 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. 199 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input.
196 /// The opamp output will be disabled when it is dropped. 200 /// The opamp output will be disabled when it is dropped.
197 #[cfg(opamp_g4)] 201 #[cfg(opamp_v5)]
198 pub fn buffer_int( 202 pub fn buffer_int(
199 &mut self, 203 &mut self,
200 pin: Peri<'_, impl NonInvertingPin<T> + crate::gpio::Pin>, 204 pin: Peri<'_, impl NonInvertingPin<T> + crate::gpio::Pin>,
@@ -204,7 +208,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
204 T::regs().csr().modify(|w| { 208 T::regs().csr().modify(|w| {
205 w.set_vp_sel(VpSel::from_bits(pin.channel())); 209 w.set_vp_sel(VpSel::from_bits(pin.channel()));
206 w.set_vm_sel(VmSel::OUTPUT); 210 w.set_vm_sel(VmSel::OUTPUT);
207 #[cfg(opamp_g4)] 211 #[cfg(opamp_v5)]
208 w.set_opaintoen(true); 212 w.set_opaintoen(true);
209 w.set_opampen(true); 213 w.set_opampen(true);
210 }); 214 });
@@ -220,7 +224,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
220 /// 224 ///
221 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. 225 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input.
222 /// The opamp output will be disabled when it is dropped. 226 /// The opamp output will be disabled when it is dropped.
223 #[cfg(opamp_g4)] 227 #[cfg(opamp_v5)]
224 pub fn pga_int( 228 pub fn pga_int(
225 &mut self, 229 &mut self,
226 pin: Peri<'_, impl NonInvertingPin<T> + crate::gpio::Pin>, 230 pin: Peri<'_, impl NonInvertingPin<T> + crate::gpio::Pin>,
@@ -257,7 +261,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
257 /// 261 ///
258 /// The returned `OpAmpInternalOutput` struct may be used as an ADC 262 /// The returned `OpAmpInternalOutput` struct may be used as an ADC
259 /// input. The opamp output will be disabled when it is dropped. 263 /// input. The opamp output will be disabled when it is dropped.
260 #[cfg(opamp_g4)] 264 #[cfg(opamp_v5)]
261 pub fn standalone_dac_int( 265 pub fn standalone_dac_int(
262 &mut self, 266 &mut self,
263 m_pin: Peri<'_, impl InvertingPin<T> + crate::gpio::Pin>, 267 m_pin: Peri<'_, impl InvertingPin<T> + crate::gpio::Pin>,
@@ -285,7 +289,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
285 /// The output pin is held within the returned [`OpAmpOutput`] struct, 289 /// The output pin is held within the returned [`OpAmpOutput`] struct,
286 /// preventing it being used elsewhere. The opamp will be disabled when 290 /// preventing it being used elsewhere. The opamp will be disabled when
287 /// the [`OpAmpOutput`] is dropped. 291 /// the [`OpAmpOutput`] is dropped.
288 #[cfg(opamp_g4)] 292 #[cfg(opamp_v5)]
289 pub fn standalone_dac_ext( 293 pub fn standalone_dac_ext(
290 &mut self, 294 &mut self,
291 m_pin: Peri<'_, impl InvertingPin<T> + crate::gpio::Pin>, 295 m_pin: Peri<'_, impl InvertingPin<T> + crate::gpio::Pin>,
@@ -315,7 +319,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
315 /// The output pin is held within the returned [`OpAmpOutput`] struct, 319 /// The output pin is held within the returned [`OpAmpOutput`] struct,
316 /// preventing it being used elsewhere. The opamp will be disabled when 320 /// preventing it being used elsewhere. The opamp will be disabled when
317 /// the [`OpAmpOutput`] is dropped. 321 /// the [`OpAmpOutput`] is dropped.
318 #[cfg(opamp_g4)] 322 #[cfg(opamp_v5)]
319 pub fn standalone_ext( 323 pub fn standalone_ext(
320 &mut self, 324 &mut self,
321 p_pin: Peri<'d, impl NonInvertingPin<T> + crate::gpio::Pin>, 325 p_pin: Peri<'d, impl NonInvertingPin<T> + crate::gpio::Pin>,
@@ -346,7 +350,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
346 /// 350 ///
347 /// The returned `OpAmpOutput` struct may be used as an ADC 351 /// The returned `OpAmpOutput` struct may be used as an ADC
348 /// input. The opamp output will be disabled when it is dropped. 352 /// input. The opamp output will be disabled when it is dropped.
349 #[cfg(opamp_g4)] 353 #[cfg(opamp_v5)]
350 pub fn standalone_int( 354 pub fn standalone_int(
351 &mut self, 355 &mut self,
352 p_pin: Peri<'d, impl NonInvertingPin<T> + crate::gpio::Pin>, 356 p_pin: Peri<'d, impl NonInvertingPin<T> + crate::gpio::Pin>,
@@ -374,7 +378,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
374 /// while for high-speed mode, only the P differential pair is calibrated. 378 /// while for high-speed mode, only the P differential pair is calibrated.
375 /// 379 ///
376 /// Calibrating a differential pair requires waiting 12ms in the worst case (binary method). 380 /// Calibrating a differential pair requires waiting 12ms in the worst case (binary method).
377 #[cfg(opamp_g4)] 381 #[cfg(opamp_v5)]
378 pub fn calibrate(&mut self) { 382 pub fn calibrate(&mut self) {
379 T::regs().csr().modify(|w| { 383 T::regs().csr().modify(|w| {
380 w.set_opampen(true); 384 w.set_opampen(true);
@@ -403,7 +407,7 @@ impl<'d, T: Instance> OpAmp<'d, T> {
403 /// The calibration range is from 0 to 31. 407 /// The calibration range is from 0 to 31.
404 /// 408 ///
405 /// The result is stored in the OPAMP_CSR register. 409 /// The result is stored in the OPAMP_CSR register.
406 #[cfg(opamp_g4)] 410 #[cfg(opamp_v5)]
407 fn calibrate_differential_pair(&mut self, pair: OpAmpDifferentialPair) { 411 fn calibrate_differential_pair(&mut self, pair: OpAmpDifferentialPair) {
408 let mut low = 0; 412 let mut low = 0;
409 let mut high = 31; 413 let mut high = 31;
@@ -452,6 +456,13 @@ impl<'d, T: Instance> OpAmp<'d, T> {
452 } 456 }
453} 457}
454 458
459#[cfg(not(any(stm32g4, stm32f3)))]
460impl<'d, T: Instance> Drop for OpAmp<'d, T> {
461 fn drop(&mut self) {
462 T::info().rcc.disable();
463 }
464}
465
455impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { 466impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> {
456 fn drop(&mut self) { 467 fn drop(&mut self) {
457 T::regs().csr().modify(|w| { 468 T::regs().csr().modify(|w| {
@@ -460,7 +471,7 @@ impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> {
460 } 471 }
461} 472}
462 473
463#[cfg(opamp_g4)] 474#[cfg(opamp_v5)]
464impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { 475impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
465 fn drop(&mut self) { 476 fn drop(&mut self) {
466 T::regs().csr().modify(|w| { 477 T::regs().csr().modify(|w| {
@@ -469,7 +480,14 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
469 } 480 }
470} 481}
471 482
483#[cfg(not(any(stm32g4, stm32f3)))]
484pub(crate) struct Info {
485 rcc: RccInfo,
486}
487
472pub(crate) trait SealedInstance { 488pub(crate) trait SealedInstance {
489 #[cfg(not(any(stm32g4, stm32f3)))]
490 fn info() -> &'static Info;
473 fn regs() -> crate::pac::opamp::Opamp; 491 fn regs() -> crate::pac::opamp::Opamp;
474} 492}
475 493
@@ -545,7 +563,7 @@ foreach_peripheral!(
545 }; 563 };
546); 564);
547 565
548#[cfg(opamp_g4)] 566#[cfg(opamp_v5)]
549macro_rules! impl_opamp_internal_output { 567macro_rules! impl_opamp_internal_output {
550 ($inst:ident, $adc:ident, $ch:expr) => { 568 ($inst:ident, $adc:ident, $ch:expr) => {
551 foreach_adc!( 569 foreach_adc!(
@@ -567,7 +585,7 @@ macro_rules! impl_opamp_internal_output {
567 }; 585 };
568} 586}
569 587
570#[cfg(opamp_g4)] 588#[cfg(opamp_v5)]
571foreach_peripheral!( 589foreach_peripheral!(
572 (opamp, OPAMP1) => { 590 (opamp, OPAMP1) => {
573 impl_opamp_internal_output!(OPAMP1, ADC1, 13); 591 impl_opamp_internal_output!(OPAMP1, ADC1, 13);
@@ -600,6 +618,15 @@ foreach_peripheral!(
600foreach_peripheral! { 618foreach_peripheral! {
601 (opamp, $inst:ident) => { 619 (opamp, $inst:ident) => {
602 impl SealedInstance for crate::peripherals::$inst { 620 impl SealedInstance for crate::peripherals::$inst {
621 // G4 and F3 use SYSCFGEN, which is always enabled
622 #[cfg(not(any(stm32g4, stm32f3)))]
623 fn info() -> &'static Info {
624 use crate::rcc::SealedRccPeripheral;
625 static INFO: Info = Info {
626 rcc: crate::peripherals::$inst::RCC_INFO,
627 };
628 &INFO
629 }
603 fn regs() -> crate::pac::opamp::Opamp { 630 fn regs() -> crate::pac::opamp::Opamp {
604 crate::pac::$inst 631 crate::pac::$inst
605 } 632 }
diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs
index 9ec4c1b43..fa5e36d06 100644
--- a/embassy-stm32/src/qspi/enums.rs
+++ b/embassy-stm32/src/qspi/enums.rs
@@ -331,3 +331,19 @@ impl From<DummyCycles> for u8 {
331 } 331 }
332 } 332 }
333} 333}
334
335#[allow(missing_docs)]
336#[derive(Copy, Clone)]
337pub enum SampleShifting {
338 None,
339 HalfCycle,
340}
341
342impl From<SampleShifting> for bool {
343 fn from(value: SampleShifting) -> Self {
344 match value {
345 SampleShifting::None => false,
346 SampleShifting::HalfCycle => true,
347 }
348 }
349}
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 0df057c53..1e20d7cd3 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -58,6 +58,8 @@ pub struct Config {
58 pub fifo_threshold: FIFOThresholdLevel, 58 pub fifo_threshold: FIFOThresholdLevel,
59 /// Minimum number of cycles that chip select must be high between issued commands 59 /// Minimum number of cycles that chip select must be high between issued commands
60 pub cs_high_time: ChipSelectHighTime, 60 pub cs_high_time: ChipSelectHighTime,
61 /// Shift sampling point of input data (none, or half-cycle)
62 pub sample_shifting: SampleShifting,
61} 63}
62 64
63impl Default for Config { 65impl Default for Config {
@@ -68,6 +70,7 @@ impl Default for Config {
68 prescaler: 128, 70 prescaler: 128,
69 fifo_threshold: FIFOThresholdLevel::_17Bytes, 71 fifo_threshold: FIFOThresholdLevel::_17Bytes,
70 cs_high_time: ChipSelectHighTime::_5Cycle, 72 cs_high_time: ChipSelectHighTime::_5Cycle,
73 sample_shifting: SampleShifting::None,
71 } 74 }
72 } 75 }
73} 76}
@@ -120,7 +123,7 @@ impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> {
120 T::REGS.cr().modify(|w| { 123 T::REGS.cr().modify(|w| {
121 w.set_en(true); 124 w.set_en(true);
122 //w.set_tcen(false); 125 //w.set_tcen(false);
123 w.set_sshift(false); 126 w.set_sshift(config.sample_shifting.into());
124 w.set_fthres(config.fifo_threshold.into()); 127 w.set_fthres(config.fifo_threshold.into());
125 w.set_prescaler(config.prescaler); 128 w.set_prescaler(config.prescaler);
126 w.set_fsel(fsel.into()); 129 w.set_fsel(fsel.into());
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index cac2a9149..c2295bab6 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -190,6 +190,8 @@ pub(crate) unsafe fn init(config: Config) {
190 // TODO 190 // TODO
191 lsi: None, 191 lsi: None,
192 lse: None, 192 lse: None,
193 #[cfg(crs)]
194 hsi48: None,
193 ); 195 );
194 196
195 RCC.ccipr() 197 RCC.ccipr()
diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs
index 3ea5c96c9..49be4af5e 100644
--- a/embassy-stm32/src/rcc/hsi48.rs
+++ b/embassy-stm32/src/rcc/hsi48.rs
@@ -39,9 +39,9 @@ pub(crate) fn init_hsi48(config: Hsi48Config) -> Hertz {
39 }); 39 });
40 40
41 // Enable HSI48 41 // Enable HSI48
42 #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0)))] 42 #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0, stm32c071)))]
43 let r = RCC.crrcr(); 43 let r = RCC.crrcr();
44 #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba))] 44 #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32c071))]
45 let r = RCC.cr(); 45 let r = RCC.cr();
46 #[cfg(any(stm32f0))] 46 #[cfg(any(stm32f0))]
47 let r = RCC.cr2(); 47 let r = RCC.cr2();
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index c50e071fb..96e628b1a 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -74,7 +74,7 @@ macro_rules! impl_peri {
74 }; 74 };
75} 75}
76 76
77#[cfg(any(rcc_c0, rcc_g0, rcc_u0))] 77#[cfg(any(rcc_c0, rcc_c0v2, rcc_g0x0, rcc_g0x1, rcc_u0))]
78#[allow(unused_imports)] 78#[allow(unused_imports)]
79use self::{McoSource as Mco1Source, McoSource as Mco2Source}; 79use self::{McoSource as Mco1Source, McoSource as Mco2Source};
80 80
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 3733fed56..c41f81816 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -95,6 +95,15 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
95 unwrap!(CLOCK_FREQS_PTR.load(core::sync::atomic::Ordering::SeqCst).as_ref()).assume_init_ref() 95 unwrap!(CLOCK_FREQS_PTR.load(core::sync::atomic::Ordering::SeqCst).as_ref()).assume_init_ref()
96} 96}
97 97
98/// Get the current clock configuration of the chip.
99pub fn clocks<'a>(_rcc: &'a crate::Peri<'a, crate::peripherals::RCC>) -> &'a Clocks {
100 // Safety: the existence of a `Peri<RCC>` means that `rcc::init()`
101 // has already been called, so `CLOCK_FREQS` must be initialized.
102 // The clocks could be modified again by `reinit()`, but reinit
103 // (for this reason) requires an exclusive reference to `Peri<RCC>`.
104 unsafe { get_freqs() }
105}
106
98pub(crate) trait SealedRccPeripheral { 107pub(crate) trait SealedRccPeripheral {
99 fn frequency() -> Hertz; 108 fn frequency() -> Hertz;
100 #[allow(dead_code)] 109 #[allow(dead_code)]
@@ -381,7 +390,7 @@ pub fn disable<T: RccPeripheral>() {
381/// 390///
382/// This should only be called after `init`. 391/// This should only be called after `init`.
383#[cfg(not(feature = "_dual-core"))] 392#[cfg(not(feature = "_dual-core"))]
384pub fn reinit(config: Config) { 393pub fn reinit<'a>(config: Config, _rcc: &'a mut crate::Peri<'a, crate::peripherals::RCC>) {
385 critical_section::with(|cs| init_rcc(cs, config)) 394 critical_section::with(|cs| init_rcc(cs, config))
386} 395}
387 396
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 97eb2eb6d..06895a99a 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::{
5 Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, 5 Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
6 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, 6 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk,
7}; 7};
8use crate::pac::rcc::vals::{Hseext, Msirgsel, Pllmboost, Pllrge}; 8use crate::pac::rcc::vals::{Hseext, Msipllfast, Msipllsel, Msirgsel, Pllmboost, Pllrge};
9#[cfg(all(peri_usb_otg_hs))] 9#[cfg(all(peri_usb_otg_hs))]
10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; 10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG};
11use crate::pac::{FLASH, PWR, RCC}; 11use crate::pac::{FLASH, PWR, RCC};
@@ -64,6 +64,46 @@ pub struct Pll {
64 pub divr: Option<PllDiv>, 64 pub divr: Option<PllDiv>,
65} 65}
66 66
67#[derive(Clone, Copy, PartialEq)]
68pub enum MsiAutoCalibration {
69 /// MSI auto-calibration is disabled
70 Disabled,
71 /// MSIS is given priority for auto-calibration
72 MSIS,
73 /// MSIK is given priority for auto-calibration
74 MSIK,
75 /// MSIS with fast mode (always on)
76 MsisFast,
77 /// MSIK with fast mode (always on)
78 MsikFast,
79}
80
81impl MsiAutoCalibration {
82 const fn default() -> Self {
83 MsiAutoCalibration::Disabled
84 }
85
86 fn base_mode(&self) -> Self {
87 match self {
88 MsiAutoCalibration::Disabled => MsiAutoCalibration::Disabled,
89 MsiAutoCalibration::MSIS => MsiAutoCalibration::MSIS,
90 MsiAutoCalibration::MSIK => MsiAutoCalibration::MSIK,
91 MsiAutoCalibration::MsisFast => MsiAutoCalibration::MSIS,
92 MsiAutoCalibration::MsikFast => MsiAutoCalibration::MSIK,
93 }
94 }
95
96 fn is_fast(&self) -> bool {
97 matches!(self, MsiAutoCalibration::MsisFast | MsiAutoCalibration::MsikFast)
98 }
99}
100
101impl Default for MsiAutoCalibration {
102 fn default() -> Self {
103 Self::default()
104 }
105}
106
67#[derive(Clone, Copy)] 107#[derive(Clone, Copy)]
68pub struct Config { 108pub struct Config {
69 // base clock sources 109 // base clock sources
@@ -95,6 +135,7 @@ pub struct Config {
95 135
96 /// Per-peripheral kernel clock selection muxes 136 /// Per-peripheral kernel clock selection muxes
97 pub mux: super::mux::ClockMux, 137 pub mux: super::mux::ClockMux,
138 pub auto_calibration: MsiAutoCalibration,
98} 139}
99 140
100impl Config { 141impl Config {
@@ -116,6 +157,7 @@ impl Config {
116 voltage_range: VoltageScale::RANGE1, 157 voltage_range: VoltageScale::RANGE1,
117 ls: crate::rcc::LsConfig::new(), 158 ls: crate::rcc::LsConfig::new(),
118 mux: super::mux::ClockMux::default(), 159 mux: super::mux::ClockMux::default(),
160 auto_calibration: MsiAutoCalibration::default(),
119 } 161 }
120 } 162 }
121} 163}
@@ -131,7 +173,42 @@ pub(crate) unsafe fn init(config: Config) {
131 PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); 173 PWR.vosr().modify(|w| w.set_vos(config.voltage_range));
132 while !PWR.vosr().read().vosrdy() {} 174 while !PWR.vosr().read().vosrdy() {}
133 175
134 let msis = config.msis.map(|range| { 176 let lse_calibration_freq = if config.auto_calibration != MsiAutoCalibration::Disabled {
177 // LSE must be configured and peripherals clocked for MSI auto-calibration
178 let lse_config = config
179 .ls
180 .lse
181 .clone()
182 .expect("LSE must be configured for MSI auto-calibration");
183 assert!(lse_config.peripherals_clocked);
184
185 // Expect less than +/- 5% deviation for LSE frequency
186 if (31_100..=34_400).contains(&lse_config.frequency.0) {
187 // Check that the calibration is applied to an active clock
188 match (
189 config.auto_calibration.base_mode(),
190 config.msis.is_some(),
191 config.msik.is_some(),
192 ) {
193 (MsiAutoCalibration::MSIS, true, _) => {
194 // MSIS is active and using LSE for auto-calibration
195 Some(lse_config.frequency)
196 }
197 (MsiAutoCalibration::MSIK, _, true) => {
198 // MSIK is active and using LSE for auto-calibration
199 Some(lse_config.frequency)
200 }
201 // improper configuration
202 _ => panic!("MSIx auto-calibration is enabled for a source that has not been configured."),
203 }
204 } else {
205 panic!("LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration");
206 }
207 } else {
208 None
209 };
210
211 let mut msis = config.msis.map(|range| {
135 // Check MSI output per RM0456 § 11.4.10 212 // Check MSI output per RM0456 § 11.4.10
136 match config.voltage_range { 213 match config.voltage_range {
137 VoltageScale::RANGE4 => { 214 VoltageScale::RANGE4 => {
@@ -156,11 +233,21 @@ pub(crate) unsafe fn init(config: Config) {
156 w.set_msipllen(false); 233 w.set_msipllen(false);
157 w.set_msison(true); 234 w.set_msison(true);
158 }); 235 });
236 let msis = if let (Some(freq), MsiAutoCalibration::MSIS) =
237 (lse_calibration_freq, config.auto_calibration.base_mode())
238 {
239 // Enable the MSIS auto-calibration feature
240 RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS));
241 RCC.cr().modify(|w| w.set_msipllen(true));
242 calculate_calibrated_msi_frequency(range, freq)
243 } else {
244 msirange_to_hertz(range)
245 };
159 while !RCC.cr().read().msisrdy() {} 246 while !RCC.cr().read().msisrdy() {}
160 msirange_to_hertz(range) 247 msis
161 }); 248 });
162 249
163 let msik = config.msik.map(|range| { 250 let mut msik = config.msik.map(|range| {
164 // Check MSI output per RM0456 § 11.4.10 251 // Check MSI output per RM0456 § 11.4.10
165 match config.voltage_range { 252 match config.voltage_range {
166 VoltageScale::RANGE4 => { 253 VoltageScale::RANGE4 => {
@@ -184,10 +271,44 @@ pub(crate) unsafe fn init(config: Config) {
184 RCC.cr().modify(|w| { 271 RCC.cr().modify(|w| {
185 w.set_msikon(true); 272 w.set_msikon(true);
186 }); 273 });
274 let msik = if let (Some(freq), MsiAutoCalibration::MSIK) =
275 (lse_calibration_freq, config.auto_calibration.base_mode())
276 {
277 // Enable the MSIK auto-calibration feature
278 RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK));
279 RCC.cr().modify(|w| w.set_msipllen(true));
280 calculate_calibrated_msi_frequency(range, freq)
281 } else {
282 msirange_to_hertz(range)
283 };
187 while !RCC.cr().read().msikrdy() {} 284 while !RCC.cr().read().msikrdy() {}
188 msirange_to_hertz(range) 285 msik
189 }); 286 });
190 287
288 if let Some(lse_freq) = lse_calibration_freq {
289 // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source.
290 if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) {
291 if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) {
292 // Clock source is shared, both will be auto calibrated, recalculate other frequency
293 match config.auto_calibration.base_mode() {
294 MsiAutoCalibration::MSIS => {
295 msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq));
296 }
297 MsiAutoCalibration::MSIK => {
298 msis = Some(calculate_calibrated_msi_frequency(msis_range, lse_freq));
299 }
300 _ => {}
301 }
302 }
303 }
304 // Check if Fast mode should be used
305 if config.auto_calibration.is_fast() {
306 RCC.cr().modify(|w| {
307 w.set_msipllfast(Msipllfast::FAST);
308 });
309 }
310 }
311
191 let hsi = config.hsi.then(|| { 312 let hsi = config.hsi.then(|| {
192 RCC.cr().modify(|w| w.set_hsion(true)); 313 RCC.cr().modify(|w| w.set_hsion(true));
193 while !RCC.cr().read().hsirdy() {} 314 while !RCC.cr().read().hsirdy() {}
@@ -514,3 +635,37 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput, voltag
514 635
515 PllOutput { p, q, r } 636 PllOutput { p, q, r }
516} 637}
638
639/// Fraction structure for MSI auto-calibration
640/// Represents the multiplier as numerator/denominator that LSE frequency is multiplied by
641#[derive(Debug, Clone, Copy)]
642struct MsiFraction {
643 numerator: u32,
644 denominator: u32,
645}
646
647impl MsiFraction {
648 const fn new(numerator: u32, denominator: u32) -> Self {
649 Self { numerator, denominator }
650 }
651
652 /// Calculate the calibrated frequency given an LSE frequency
653 fn calculate_frequency(&self, lse_freq: Hertz) -> Hertz {
654 Hertz(lse_freq.0 * self.numerator / self.denominator)
655 }
656}
657
658fn get_msi_calibration_fraction(range: Msirange) -> MsiFraction {
659 // Exploiting the MSIx internals to make calculations compact
660 let denominator = (range as u32 & 0x03) + 1;
661 // Base multipliers are deduced from Table 82: MSI oscillator characteristics in data sheet
662 let numerator = [1465, 122, 94, 12][range as usize >> 2];
663
664 MsiFraction::new(numerator, denominator)
665}
666
667/// Calculate the calibrated MSI frequency for a given range and LSE frequency
668fn calculate_calibrated_msi_frequency(range: Msirange, lse_freq: Hertz) -> Hertz {
669 let fraction = get_msi_calibration_fraction(range);
670 fraction.calculate_frequency(lse_freq)
671}
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index b9fc4e423..b494997b3 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -176,6 +176,7 @@ pub(crate) unsafe fn init(config: Config) {
176 // TODO 176 // TODO
177 lse: None, 177 lse: None,
178 lsi: None, 178 lsi: None,
179 pll1_p: None,
179 pll1_q: None, 180 pll1_q: None,
180 ); 181 );
181} 182}
diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs
index cd075f3de..78ccd3e6c 100644
--- a/embassy-stm32/src/rtc/low_power.rs
+++ b/embassy-stm32/src/rtc/low_power.rs
@@ -66,7 +66,7 @@ pub(crate) enum WakeupPrescaler {
66} 66}
67 67
68#[cfg(any( 68#[cfg(any(
69 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0 69 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba
70))] 70))]
71impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 71impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
72 fn from(val: WakeupPrescaler) -> Self { 72 fn from(val: WakeupPrescaler) -> Self {
@@ -82,7 +82,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
82} 82}
83 83
84#[cfg(any( 84#[cfg(any(
85 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0 85 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba
86))] 86))]
87impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 87impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
88 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { 88 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
@@ -227,7 +227,7 @@ impl Rtc {
227 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); 227 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
228 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() }; 228 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };
229 229
230 #[cfg(not(any(stm32u5, stm32u0)))] 230 #[cfg(not(any(stm32u5, stm32u0, stm32wba)))]
231 { 231 {
232 use crate::pac::EXTI; 232 use crate::pac::EXTI;
233 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 233 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
@@ -247,5 +247,11 @@ impl Rtc {
247 RCC.srdamr().modify(|w| w.set_rtcapbamen(true)); 247 RCC.srdamr().modify(|w| w.set_rtcapbamen(true));
248 RCC.apb3smenr().modify(|w| w.set_rtcapbsmen(true)); 248 RCC.apb3smenr().modify(|w| w.set_rtcapbsmen(true));
249 } 249 }
250 #[cfg(stm32wba)]
251 {
252 use crate::pac::RCC;
253 // RCC.srdamr().modify(|w| w.set_rtcapbamen(true));
254 RCC.apb7smenr().modify(|w| w.set_rtcapbsmen(true));
255 }
250 } 256 }
251} 257}
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 49f423f37..449f3008a 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -25,7 +25,7 @@ use crate::time::Hertz;
25 ), 25 ),
26 path = "v2.rs" 26 path = "v2.rs"
27)] 27)]
28#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs), path = "v3.rs")] 28#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs, rtc_v3c0), path = "v3.rs")]
29mod _version; 29mod _version;
30#[allow(unused_imports)] 30#[allow(unused_imports)]
31pub use _version::*; 31pub use _version::*;
@@ -296,7 +296,7 @@ trait SealedInstance {
296 const BACKUP_REGISTER_COUNT: usize; 296 const BACKUP_REGISTER_COUNT: usize;
297 297
298 #[cfg(feature = "low-power")] 298 #[cfg(feature = "low-power")]
299 #[cfg(not(any(stm32u5, stm32u0)))] 299 #[cfg(not(any(stm32wba, stm32u5, stm32u0)))]
300 const EXTI_WAKEUP_LINE: usize; 300 const EXTI_WAKEUP_LINE: usize;
301 301
302 #[cfg(feature = "low-power")] 302 #[cfg(feature = "low-power")]
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 39aa6c5cb..d0b52049e 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -146,7 +146,7 @@ impl SealedInstance for crate::peripherals::RTC {
146 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; 146 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
147 } else if #[cfg(any(stm32g0, stm32u0))] { 147 } else if #[cfg(any(stm32g0, stm32u0))] {
148 type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP; 148 type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP;
149 } else if #[cfg(any(stm32l5, stm32h5, stm32u5))] { 149 } else if #[cfg(any(stm32l5, stm32h5, stm32u5, stm32wba))] {
150 type WakeupInterrupt = crate::interrupt::typelevel::RTC; 150 type WakeupInterrupt = crate::interrupt::typelevel::RTC;
151 } 151 }
152 ); 152 );
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 6a02aae70..6e5d735d7 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -32,25 +32,48 @@ pub struct InterruptHandler<T: Instance> {
32} 32}
33 33
34impl<T: Instance> InterruptHandler<T> { 34impl<T: Instance> InterruptHandler<T> {
35 fn data_interrupts(enable: bool) { 35 fn enable_interrupts() {
36 let regs = T::regs(); 36 let regs = T::regs();
37 regs.maskr().write(|w| { 37 regs.maskr().write(|w| {
38 w.set_dcrcfailie(enable); 38 w.set_dcrcfailie(true);
39 w.set_dtimeoutie(enable); 39 w.set_dtimeoutie(true);
40 w.set_dataendie(enable); 40 w.set_dataendie(true);
41 w.set_dbckendie(true);
41 42
42 #[cfg(sdmmc_v1)] 43 #[cfg(sdmmc_v1)]
43 w.set_stbiterre(enable); 44 w.set_stbiterre(true);
44 #[cfg(sdmmc_v2)] 45 #[cfg(sdmmc_v2)]
45 w.set_dabortie(enable); 46 w.set_dabortie(true);
46 }); 47 });
47 } 48 }
48} 49}
49 50
50impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 51impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
51 unsafe fn on_interrupt() { 52 unsafe fn on_interrupt() {
52 Self::data_interrupts(false);
53 T::state().wake(); 53 T::state().wake();
54 let status = T::regs().star().read();
55 T::regs().maskr().modify(|w| {
56 if status.dcrcfail() {
57 w.set_dcrcfailie(false)
58 }
59 if status.dtimeout() {
60 w.set_dtimeoutie(false)
61 }
62 if status.dataend() {
63 w.set_dataendie(false)
64 }
65 if status.dbckend() {
66 w.set_dbckendie(false)
67 }
68 #[cfg(sdmmc_v1)]
69 if status.stbiterr() {
70 w.set_stbiterre(false)
71 }
72 #[cfg(sdmmc_v2)]
73 if status.dabort() {
74 w.set_dabortie(false)
75 }
76 });
54 } 77 }
55} 78}
56 79
@@ -225,8 +248,7 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
225 return Ok((true, 0, ker_ck)); 248 return Ok((true, 0, ker_ck));
226 } 249 }
227 250
228 // `ker_ck / sdmmc_ck` rounded up 251 let clk_div = match ker_ck.0.div_ceil(sdmmc_ck) {
229 let clk_div = match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
230 0 | 1 => Ok(0), 252 0 | 1 => Ok(0),
231 x @ 2..=258 => Ok((x - 2) as u8), 253 x @ 2..=258 => Ok((x - 2) as u8),
232 _ => Err(Error::BadClock), 254 _ => Err(Error::BadClock),
@@ -244,12 +266,11 @@ fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u8, Hertz), Error> {
244/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency. 266/// `clk_div` is the divisor register value and `clk_f` is the resulting new clock frequency.
245#[cfg(sdmmc_v2)] 267#[cfg(sdmmc_v2)]
246fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> { 268fn clk_div(ker_ck: Hertz, sdmmc_ck: u32) -> Result<(bool, u16, Hertz), Error> {
247 // `ker_ck / sdmmc_ck` rounded up 269 match ker_ck.0.div_ceil(sdmmc_ck) {
248 match (ker_ck.0 + sdmmc_ck - 1) / sdmmc_ck {
249 0 | 1 => Ok((false, 0, ker_ck)), 270 0 | 1 => Ok((false, 0, ker_ck)),
250 x @ 2..=2046 => { 271 x @ 2..=2046 => {
251 // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2] 272 // SDMMC_CK frequency = SDMMCCLK / [CLKDIV * 2]
252 let clk_div = ((x + 1) / 2) as u16; 273 let clk_div = x.div_ceil(2) as u16;
253 let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2)); 274 let clk = Hertz(ker_ck.0 / (clk_div as u32 * 2));
254 275
255 Ok((false, clk_div, clk)) 276 Ok((false, clk_div, clk))
@@ -751,7 +772,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
751 Self::wait_idle(); 772 Self::wait_idle();
752 Self::clear_interrupt_flags(); 773 Self::clear_interrupt_flags();
753 774
754 regs.dtimer().write(|w| w.set_datatime(config.data_transfer_timeout));
755 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 775 regs.dlenr().write(|w| w.set_datalength(length_bytes));
756 776
757 #[cfg(sdmmc_v1)] 777 #[cfg(sdmmc_v1)]
@@ -789,8 +809,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
789 Self::wait_idle(); 809 Self::wait_idle();
790 Self::clear_interrupt_flags(); 810 Self::clear_interrupt_flags();
791 811
792 regs.dtimer()
793 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
794 regs.dlenr().write(|w| w.set_datalength(length_bytes)); 812 regs.dlenr().write(|w| w.set_datalength(length_bytes));
795 813
796 #[cfg(sdmmc_v1)] 814 #[cfg(sdmmc_v1)]
@@ -1007,14 +1025,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1007 // Wait for the abort 1025 // Wait for the abort
1008 while Self::data_active() {} 1026 while Self::data_active() {}
1009 } 1027 }
1010 InterruptHandler::<T>::data_interrupts(false); 1028 regs.maskr().write(|_| ()); // disable irqs
1011 Self::clear_interrupt_flags(); 1029 Self::clear_interrupt_flags();
1012 Self::stop_datapath(); 1030 Self::stop_datapath();
1013 } 1031 }
1014 1032
1015 /// Wait for a previously started datapath transfer to complete from an interrupt. 1033 /// Wait for a previously started datapath transfer to complete from an interrupt.
1016 #[inline] 1034 #[inline]
1017 async fn complete_datapath_transfer() -> Result<(), Error> { 1035 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> {
1018 let regs = T::regs(); 1036 let regs = T::regs();
1019 1037
1020 let res = poll_fn(|cx| { 1038 let res = poll_fn(|cx| {
@@ -1034,7 +1052,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1034 if status.stbiterr() { 1052 if status.stbiterr() {
1035 return Poll::Ready(Err(Error::StBitErr)); 1053 return Poll::Ready(Err(Error::StBitErr));
1036 } 1054 }
1037 if status.dataend() { 1055 let done = match block {
1056 true => status.dbckend(),
1057 false => status.dataend(),
1058 };
1059 if done {
1038 return Poll::Ready(Ok(())); 1060 return Poll::Ready(Ok(()));
1039 } 1061 }
1040 Poll::Pending 1062 Poll::Pending
@@ -1072,10 +1094,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1072 512, 1094 512,
1073 9, 1095 9,
1074 ); 1096 );
1075 InterruptHandler::<T>::data_interrupts(true); 1097 InterruptHandler::<T>::enable_interrupts();
1076 Self::cmd(common_cmd::read_single_block(address), true)?; 1098 Self::cmd(common_cmd::read_single_block(address), true)?;
1077 1099
1078 let res = Self::complete_datapath_transfer().await; 1100 let res = Self::complete_datapath_transfer(true).await;
1079 1101
1080 if res.is_ok() { 1102 if res.is_ok() {
1081 on_drop.defuse(); 1103 on_drop.defuse();
@@ -1105,7 +1127,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1105 }; 1127 };
1106 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 1128 Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16
1107 1129
1108 let regs = T::regs();
1109 let on_drop = OnDrop::new(|| Self::on_drop()); 1130 let on_drop = OnDrop::new(|| Self::on_drop());
1110 1131
1111 let transfer = Self::prepare_datapath_read( 1132 let transfer = Self::prepare_datapath_read(
@@ -1116,30 +1137,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1116 512 * blocks.len() as u32, 1137 512 * blocks.len() as u32,
1117 9, 1138 9,
1118 ); 1139 );
1119 InterruptHandler::<T>::data_interrupts(true); 1140 InterruptHandler::<T>::enable_interrupts();
1120 1141
1121 Self::cmd(common_cmd::read_multiple_blocks(address), true)?; 1142 Self::cmd(common_cmd::read_multiple_blocks(address), true)?;
1122 1143
1123 let res = poll_fn(|cx| { 1144 let res = Self::complete_datapath_transfer(false).await;
1124 T::state().register(cx.waker());
1125 let status = regs.star().read();
1126
1127 if status.dcrcfail() {
1128 return Poll::Ready(Err(Error::Crc));
1129 }
1130 if status.dtimeout() {
1131 return Poll::Ready(Err(Error::Timeout));
1132 }
1133 #[cfg(sdmmc_v1)]
1134 if status.stbiterr() {
1135 return Poll::Ready(Err(Error::StBitErr));
1136 }
1137 if status.dataend() {
1138 return Poll::Ready(Ok(()));
1139 }
1140 Poll::Pending
1141 })
1142 .await;
1143 1145
1144 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 1146 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1145 Self::clear_interrupt_flags(); 1147 Self::clear_interrupt_flags();
@@ -1174,12 +1176,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1174 Self::cmd(common_cmd::write_single_block(address), true)?; 1176 Self::cmd(common_cmd::write_single_block(address), true)?;
1175 1177
1176 let transfer = self.prepare_datapath_write(buffer, 512, 9); 1178 let transfer = self.prepare_datapath_write(buffer, 512, 9);
1177 InterruptHandler::<T>::data_interrupts(true); 1179 InterruptHandler::<T>::enable_interrupts();
1178 1180
1179 #[cfg(sdmmc_v2)] 1181 #[cfg(sdmmc_v2)]
1180 Self::cmd(common_cmd::write_single_block(address), true)?; 1182 Self::cmd(common_cmd::write_single_block(address), true)?;
1181 1183
1182 let res = Self::complete_datapath_transfer().await; 1184 let res = Self::complete_datapath_transfer(true).await;
1183 1185
1184 match res { 1186 match res {
1185 Ok(_) => { 1187 Ok(_) => {
@@ -1230,7 +1232,6 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1230 1232
1231 let block_count = blocks.len(); 1233 let block_count = blocks.len();
1232 1234
1233 let regs = T::regs();
1234 let on_drop = OnDrop::new(|| Self::on_drop()); 1235 let on_drop = OnDrop::new(|| Self::on_drop());
1235 1236
1236 #[cfg(sdmmc_v1)] 1237 #[cfg(sdmmc_v1)]
@@ -1238,36 +1239,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1238 1239
1239 // Setup write command 1240 // Setup write command
1240 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9); 1241 let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9);
1241 InterruptHandler::<T>::data_interrupts(true); 1242 InterruptHandler::<T>::enable_interrupts();
1242 1243
1243 #[cfg(sdmmc_v2)] 1244 #[cfg(sdmmc_v2)]
1244 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 1245 Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25
1245 1246
1246 let res = poll_fn(|cx| { 1247 let res = Self::complete_datapath_transfer(false).await;
1247 T::state().register(cx.waker());
1248
1249 let status = regs.star().read();
1250
1251 if status.dcrcfail() {
1252 return Poll::Ready(Err(Error::Crc));
1253 }
1254 if status.dtimeout() {
1255 return Poll::Ready(Err(Error::Timeout));
1256 }
1257 if status.txunderr() {
1258 return Poll::Ready(Err(Error::Underrun));
1259 }
1260 #[cfg(sdmmc_v1)]
1261 if status.stbiterr() {
1262 return Poll::Ready(Err(Error::StBitErr));
1263 }
1264 if status.dataend() {
1265 return Poll::Ready(Ok(()));
1266 }
1267
1268 Poll::Pending
1269 })
1270 .await;
1271 1248
1272 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 1249 Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12
1273 Self::clear_interrupt_flags(); 1250 Self::clear_interrupt_flags();
@@ -1349,6 +1326,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1349 #[cfg(sdmmc_v1)] 1326 #[cfg(sdmmc_v1)]
1350 w.set_bypass(_bypass); 1327 w.set_bypass(_bypass);
1351 }); 1328 });
1329 regs.dtimer()
1330 .write(|w| w.set_datatime(self.config.data_transfer_timeout));
1352 1331
1353 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); 1332 regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8));
1354 Self::cmd(common_cmd::idle(), false)?; 1333 Self::cmd(common_cmd::idle(), false)?;
@@ -1600,10 +1579,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1600 64, 1579 64,
1601 6, 1580 6,
1602 ); 1581 );
1603 InterruptHandler::<T>::data_interrupts(true); 1582 InterruptHandler::<T>::enable_interrupts();
1604 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 1583 Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1605 1584
1606 let res = Self::complete_datapath_transfer().await; 1585 let res = Self::complete_datapath_transfer(true).await;
1607 1586
1608 // Host is allowed to use the new functions at least 8 1587 // Host is allowed to use the new functions at least 8
1609 // clocks after the end of the switch command 1588 // clocks after the end of the switch command
@@ -1660,10 +1639,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1660 8, 1639 8,
1661 3, 1640 3,
1662 ); 1641 );
1663 InterruptHandler::<T>::data_interrupts(true); 1642 InterruptHandler::<T>::enable_interrupts();
1664 Self::cmd(sd_cmd::send_scr(), true)?; 1643 Self::cmd(sd_cmd::send_scr(), true)?;
1665 1644
1666 let res = Self::complete_datapath_transfer().await; 1645 let res = Self::complete_datapath_transfer(true).await;
1667 1646
1668 if res.is_ok() { 1647 if res.is_ok() {
1669 on_drop.defuse(); 1648 on_drop.defuse();
@@ -1706,10 +1685,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1706 64, 1685 64,
1707 6, 1686 6,
1708 ); 1687 );
1709 InterruptHandler::<T>::data_interrupts(true); 1688 InterruptHandler::<T>::enable_interrupts();
1710 Self::cmd(sd_cmd::sd_status(), true)?; 1689 Self::cmd(sd_cmd::sd_status(), true)?;
1711 1690
1712 let res = Self::complete_datapath_transfer().await; 1691 let res = Self::complete_datapath_transfer(true).await;
1713 1692
1714 if res.is_ok() { 1693 if res.is_ok() {
1715 on_drop.defuse(); 1694 on_drop.defuse();
@@ -1756,10 +1735,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1756 512, 1735 512,
1757 9, 1736 9,
1758 ); 1737 );
1759 InterruptHandler::<T>::data_interrupts(true); 1738 InterruptHandler::<T>::enable_interrupts();
1760 Self::cmd(emmc_cmd::send_ext_csd(), true)?; 1739 Self::cmd(emmc_cmd::send_ext_csd(), true)?;
1761 1740
1762 let res = Self::complete_datapath_transfer().await; 1741 let res = Self::complete_datapath_transfer(true).await;
1763 1742
1764 if res.is_ok() { 1743 if res.is_ok() {
1765 on_drop.defuse(); 1744 on_drop.defuse();
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 9e2ba093a..c8d83f07e 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -843,7 +843,7 @@ impl<'d> Spi<'d, Async> {
843 843
844 set_rxdmaen(self.info.regs, true); 844 set_rxdmaen(self.info.regs, true);
845 845
846 let rx_src = self.info.regs.rx_ptr(); 846 let rx_src = self.info.regs.rx_ptr::<W>();
847 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; 847 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
848 848
849 let tx_dst: *mut W = self.info.regs.tx_ptr(); 849 let tx_dst: *mut W = self.info.regs.tx_ptr();
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 8eec6c0c7..b00cc18ad 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -5,14 +5,12 @@ use core::marker::PhantomData;
5use stm32_metapac::timer::vals::Ckd; 5use stm32_metapac::timer::vals::Ckd;
6 6
7use super::low_level::{CountingMode, OutputPolarity, Timer}; 7use super::low_level::{CountingMode, OutputPolarity, Timer};
8use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin}; 8use super::simple_pwm::PwmPin;
9use super::{ 9use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
10 AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin,
11 Channel4ComplementaryPin,
12};
13use crate::gpio::{AnyPin, OutputType}; 10use crate::gpio::{AnyPin, OutputType};
14use crate::time::Hertz; 11use crate::time::Hertz;
15use crate::timer::low_level::OutputCompareMode; 12use crate::timer::low_level::OutputCompareMode;
13use crate::timer::TimerChannel;
16use crate::Peri; 14use crate::Peri;
17 15
18/// Complementary PWM pin wrapper. 16/// Complementary PWM pin wrapper.
@@ -23,32 +21,23 @@ pub struct ComplementaryPwmPin<'d, T, C> {
23 phantom: PhantomData<(T, C)>, 21 phantom: PhantomData<(T, C)>,
24} 22}
25 23
26macro_rules! complementary_channel_impl { 24impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> {
27 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 25 /// Create a new complementary PWM pin instance.
28 impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> { 26 pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
29 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] 27 critical_section::with(|_| {
30 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, output_type: OutputType) -> Self { 28 pin.set_low();
31 critical_section::with(|_| { 29 pin.set_as_af(
32 pin.set_low(); 30 pin.af_num(),
33 pin.set_as_af( 31 crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
34 pin.af_num(), 32 );
35 crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh), 33 });
36 ); 34 ComplementaryPwmPin {
37 }); 35 _pin: pin.into(),
38 ComplementaryPwmPin { 36 phantom: PhantomData,
39 _pin: pin.into(),
40 phantom: PhantomData,
41 }
42 }
43 } 37 }
44 }; 38 }
45} 39}
46 40
47complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin);
48complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
49complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
50complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
51
52/// PWM driver with support for standard and complementary outputs. 41/// PWM driver with support for standard and complementary outputs.
53pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { 42pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> {
54 inner: Timer<'d, T>, 43 inner: Timer<'d, T>,
@@ -88,6 +77,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
88 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); 77 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
89 this.inner.set_output_compare_preload(channel, true); 78 this.inner.set_output_compare_preload(channel, true);
90 }); 79 });
80 this.inner.set_autoreload_preload(true);
91 81
92 this 82 this
93 } 83 }
@@ -121,7 +111,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
121 /// 111 ///
122 /// This value depends on the configured frequency and the timer's clock rate from RCC. 112 /// This value depends on the configured frequency and the timer's clock rate from RCC.
123 pub fn get_max_duty(&self) -> u16 { 113 pub fn get_max_duty(&self) -> u16 {
124 self.inner.get_max_compare_value() as u16 + 1 114 if self.inner.get_counting_mode().is_center_aligned() {
115 self.inner.get_max_compare_value() as u16
116 } else {
117 self.inner.get_max_compare_value() as u16 + 1
118 }
125 } 119 }
126 120
127 /// Set the duty for a given channel. 121 /// Set the duty for a given channel.
@@ -171,7 +165,11 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<
171 } 165 }
172 166
173 fn get_max_duty(&self) -> Self::Duty { 167 fn get_max_duty(&self) -> Self::Duty {
174 self.inner.get_max_compare_value() as u16 + 1 168 if self.inner.get_counting_mode().is_center_aligned() {
169 self.inner.get_max_compare_value() as u16
170 } else {
171 self.inner.get_max_compare_value() as u16 + 1
172 }
175 } 173 }
176 174
177 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 175 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index ec8b1ddf1..dda33e7f1 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -6,14 +6,12 @@ use core::pin::Pin;
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; 8use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
9use super::{ 9use super::{CaptureCompareInterruptHandler, Channel, GeneralInstance4Channel, TimerPin};
10 CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
11 GeneralInstance4Channel,
12};
13pub use super::{Ch1, Ch2, Ch3, Ch4}; 10pub use super::{Ch1, Ch2, Ch3, Ch4};
14use crate::gpio::{AfType, AnyPin, Pull}; 11use crate::gpio::{AfType, AnyPin, Pull};
15use crate::interrupt::typelevel::{Binding, Interrupt}; 12use crate::interrupt::typelevel::{Binding, Interrupt};
16use crate::time::Hertz; 13use crate::time::Hertz;
14use crate::timer::TimerChannel;
17use crate::Peri; 15use crate::Peri;
18 16
19/// Capture pin wrapper. 17/// Capture pin wrapper.
@@ -23,27 +21,17 @@ pub struct CapturePin<'d, T, C> {
23 _pin: Peri<'d, AnyPin>, 21 _pin: Peri<'d, AnyPin>,
24 phantom: PhantomData<(T, C)>, 22 phantom: PhantomData<(T, C)>,
25} 23}
26 24impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
27macro_rules! channel_impl { 25 /// Create a new capture pin instance.
28 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 26 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
29 impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> { 27 pin.set_as_af(pin.af_num(), AfType::input(pull));
30 #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")] 28 CapturePin {
31 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, pull: Pull) -> Self { 29 _pin: pin.into(),
32 pin.set_as_af(pin.af_num(), AfType::input(pull)); 30 phantom: PhantomData,
33 CapturePin {
34 _pin: pin.into(),
35 phantom: PhantomData,
36 }
37 }
38 } 31 }
39 }; 32 }
40} 33}
41 34
42channel_impl!(new_ch1, Ch1, Channel1Pin);
43channel_impl!(new_ch2, Ch2, Channel2Pin);
44channel_impl!(new_ch3, Ch3, Channel3Pin);
45channel_impl!(new_ch4, Ch4, Channel4Pin);
46
47/// Input capture driver. 35/// Input capture driver.
48pub struct InputCapture<'d, T: GeneralInstance4Channel> { 36pub struct InputCapture<'d, T: GeneralInstance4Channel> {
49 inner: Timer<'d, T>, 37 inner: Timer<'d, T>,
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index b29382fc8..7062f5f4c 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -51,6 +51,80 @@ pub enum Ch3 {}
51/// Channel 4 marker type. 51/// Channel 4 marker type.
52pub enum Ch4 {} 52pub enum Ch4 {}
53 53
54/// Timer channel trait.
55#[allow(private_bounds)]
56pub trait TimerChannel: SealedTimerChannel {
57 /// The runtime channel.
58 const CHANNEL: Channel;
59}
60
61trait SealedTimerChannel {}
62
63impl TimerChannel for Ch1 {
64 const CHANNEL: Channel = Channel::Ch1;
65}
66
67impl TimerChannel for Ch2 {
68 const CHANNEL: Channel = Channel::Ch2;
69}
70
71impl TimerChannel for Ch3 {
72 const CHANNEL: Channel = Channel::Ch3;
73}
74
75impl TimerChannel for Ch4 {
76 const CHANNEL: Channel = Channel::Ch4;
77}
78
79impl SealedTimerChannel for Ch1 {}
80impl SealedTimerChannel for Ch2 {}
81impl SealedTimerChannel for Ch3 {}
82impl SealedTimerChannel for Ch4 {}
83
84/// Timer break input.
85#[derive(Clone, Copy)]
86pub enum BkIn {
87 /// Break input 1.
88 BkIn1,
89 /// Break input 2.
90 BkIn2,
91}
92
93impl BkIn {
94 /// Get the channel index (0..3)
95 pub fn index(&self) -> usize {
96 match self {
97 BkIn::BkIn1 => 0,
98 BkIn::BkIn2 => 1,
99 }
100 }
101}
102
103/// Break input 1 marker type.
104pub enum BkIn1 {}
105/// Break input 2 marker type.
106pub enum BkIn2 {}
107
108/// Timer channel trait.
109#[allow(private_bounds)]
110pub trait BreakInput: SealedBreakInput {
111 /// The runtim timer channel.
112 const INPUT: BkIn;
113}
114
115trait SealedBreakInput {}
116
117impl BreakInput for BkIn1 {
118 const INPUT: BkIn = BkIn::BkIn1;
119}
120
121impl BreakInput for BkIn2 {
122 const INPUT: BkIn = BkIn::BkIn2;
123}
124
125impl SealedBreakInput for BkIn1 {}
126impl SealedBreakInput for BkIn2 {}
127
54/// Amount of bits of a timer. 128/// Amount of bits of a timer.
55#[derive(Clone, Copy, PartialEq, Eq, Debug)] 129#[derive(Clone, Copy, PartialEq, Eq, Debug)]
56#[cfg_attr(feature = "defmt", derive(defmt::Format))] 130#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -149,33 +223,20 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
149/// Advanced 16-bit timer with 4 channels instance. 223/// Advanced 16-bit timer with 4 channels instance.
150pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} 224pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
151 225
152pin_trait!(Channel1Pin, GeneralInstance4Channel); 226pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
153pin_trait!(Channel2Pin, GeneralInstance4Channel);
154pin_trait!(Channel3Pin, GeneralInstance4Channel);
155pin_trait!(Channel4Pin, GeneralInstance4Channel);
156pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); 227pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
157 228
158pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); 229pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
159pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
160pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
161pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
162
163pin_trait!(BreakInputPin, AdvancedInstance4Channel);
164pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
165 230
166pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); 231pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
167pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
168 232
169pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); 233pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput);
170pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); 234pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
171 235
172// Update Event trigger DMA for every timer 236// Update Event trigger DMA for every timer
173dma_trait!(UpDma, BasicInstance); 237dma_trait!(UpDma, BasicInstance);
174 238
175dma_trait!(Ch1Dma, GeneralInstance4Channel); 239dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
176dma_trait!(Ch2Dma, GeneralInstance4Channel);
177dma_trait!(Ch3Dma, GeneralInstance4Channel);
178dma_trait!(Ch4Dma, GeneralInstance4Channel);
179 240
180#[allow(unused)] 241#[allow(unused)]
181macro_rules! impl_core_timer { 242macro_rules! impl_core_timer {
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index 933165ef9..498d9c082 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -7,11 +7,9 @@ use core::pin::Pin;
7use core::task::{Context, Poll}; 7use core::task::{Context, Poll};
8 8
9use super::low_level::{ 9use super::low_level::{
10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource, 10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
11};
12use super::{
13 CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, ExternalTriggerPin, GeneralInstance4Channel,
14}; 11};
12use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin};
15pub use super::{Ch1, Ch2}; 13pub use super::{Ch1, Ch2};
16use crate::gpio::{AfType, AnyPin, Pull}; 14use crate::gpio::{AfType, AnyPin, Pull};
17use crate::interrupt::typelevel::{Binding, Interrupt}; 15use crate::interrupt::typelevel::{Binding, Interrupt};
@@ -48,24 +46,78 @@ pub struct TriggerPin<'d, T, C> {
48 phantom: PhantomData<(T, C)>, 46 phantom: PhantomData<(T, C)>,
49} 47}
50 48
51macro_rules! channel_impl { 49trait SealedTriggerSource {}
52 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 50
53 impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, $channel> { 51/// Marker trait for a trigger source.
54 #[doc = concat!("Create a new ", stringify!($channel), " trigger pin instance.")] 52#[expect(private_bounds)]
55 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, pull: Pull) -> Self { 53pub trait TriggerSource: SealedTriggerSource {}
56 pin.set_as_af(pin.af_num(), AfType::input(pull)); 54
57 TriggerPin { 55impl TriggerSource for Ch1 {}
58 _pin: pin.into(), 56impl TriggerSource for Ch2 {}
59 phantom: PhantomData, 57impl TriggerSource for Ext {}
60 } 58
61 } 59impl SealedTriggerSource for Ch1 {}
62 } 60impl SealedTriggerSource for Ch2 {}
63 }; 61impl SealedTriggerSource for Ext {}
62
63trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
64
65/// Marker trait for a trigger pin.
66#[expect(private_bounds)]
67// TODO: find better naming scheme than prefixing all pin traits with "Timer".
68// The trait name cannot conflict with the corresponding type's name.
69// Applies to other timer submodules as well.
70pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
71 /// Get the AF number needed to use this pin as a trigger source.
72 fn af_num(&self) -> u8;
73}
74
75impl<T, P, C> TimerTriggerPin<T, C> for P
76where
77 T: GeneralInstance4Channel,
78 P: TimerPin<T, C>,
79 C: super::TimerChannel + TriggerSource,
80{
81 fn af_num(&self) -> u8 {
82 TimerPin::af_num(self)
83 }
84}
85
86impl<T, P> TimerTriggerPin<T, Ext> for P
87where
88 T: GeneralInstance4Channel,
89 P: ExternalTriggerPin<T>,
90{
91 fn af_num(&self) -> u8 {
92 ExternalTriggerPin::af_num(self)
93 }
94}
95
96impl<T, P, C> SealedTimerTriggerPin<T, C> for P
97where
98 T: GeneralInstance4Channel,
99 P: TimerPin<T, C>,
100 C: super::TimerChannel + TriggerSource,
101{
64} 102}
65 103
66channel_impl!(new_ch1, Ch1, Channel1Pin); 104impl<T, P> SealedTimerTriggerPin<T, Ext> for P
67channel_impl!(new_ch2, Ch2, Channel2Pin); 105where
68channel_impl!(new_ext, Ext, ExternalTriggerPin); 106 T: GeneralInstance4Channel,
107 P: ExternalTriggerPin<T>,
108{
109}
110
111impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
112 /// "Create a new Ch1 trigger pin instance.
113 pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
114 pin.set_as_af(pin.af_num(), AfType::input(pull));
115 TriggerPin {
116 _pin: pin.into(),
117 phantom: PhantomData,
118 }
119 }
120}
69 121
70/// One pulse driver. 122/// One pulse driver.
71/// 123///
@@ -89,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
89 ) -> Self { 141 ) -> Self {
90 let mut this = Self { inner: Timer::new(tim) }; 142 let mut this = Self { inner: Timer::new(tim) };
91 143
92 this.inner.set_trigger_source(TriggerSource::TI1F_ED); 144 this.inner.set_trigger_source(Ts::TI1F_ED);
93 this.inner 145 this.inner
94 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); 146 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
95 this.inner 147 this.inner
@@ -114,7 +166,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
114 ) -> Self { 166 ) -> Self {
115 let mut this = Self { inner: Timer::new(tim) }; 167 let mut this = Self { inner: Timer::new(tim) };
116 168
117 this.inner.set_trigger_source(TriggerSource::TI1FP1); 169 this.inner.set_trigger_source(Ts::TI1FP1);
118 this.inner 170 this.inner
119 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); 171 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
120 this.inner 172 this.inner
@@ -131,7 +183,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
131 /// as an output. 183 /// as an output.
132 pub fn new_ch2( 184 pub fn new_ch2(
133 tim: Peri<'d, T>, 185 tim: Peri<'d, T>,
134 _pin: TriggerPin<'d, T, Ch1>, 186 _pin: TriggerPin<'d, T, Ch2>,
135 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd, 187 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
136 freq: Hertz, 188 freq: Hertz,
137 pulse_end: u32, 189 pulse_end: u32,
@@ -140,7 +192,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
140 ) -> Self { 192 ) -> Self {
141 let mut this = Self { inner: Timer::new(tim) }; 193 let mut this = Self { inner: Timer::new(tim) };
142 194
143 this.inner.set_trigger_source(TriggerSource::TI2FP2); 195 this.inner.set_trigger_source(Ts::TI2FP2);
144 this.inner 196 this.inner
145 .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal); 197 .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
146 this.inner 198 this.inner
@@ -172,7 +224,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
172 // No filtering 224 // No filtering
173 r.set_etf(FilterValue::NO_FILTER); 225 r.set_etf(FilterValue::NO_FILTER);
174 }); 226 });
175 this.inner.set_trigger_source(TriggerSource::ETRF); 227 this.inner.set_trigger_source(Ts::ETRF);
176 this.new_inner(freq, pulse_end, counting_mode); 228 this.new_inner(freq, pulse_end, counting_mode);
177 229
178 this 230 this
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index 98b798634..1e55f2919 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -1,12 +1,16 @@
1//! PWM Input driver. 1//! PWM Input driver.
2 2
3use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; 3use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
4use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel}; 4use super::{Ch1, Ch2, Channel, GeneralInstance4Channel, TimerPin};
5use crate::gpio::{AfType, Pull}; 5use crate::gpio::{AfType, Pull};
6use crate::time::Hertz; 6use crate::time::Hertz;
7use crate::Peri; 7use crate::Peri;
8 8
9/// PWM Input driver. 9/// PWM Input driver.
10///
11/// Only works with CH1 or CH2
12/// Note: Not all timer peripherals are supported
13/// Double check your chips reference manual
10pub struct PwmInput<'d, T: GeneralInstance4Channel> { 14pub struct PwmInput<'d, T: GeneralInstance4Channel> {
11 channel: Channel, 15 channel: Channel,
12 inner: Timer<'d, T>, 16 inner: Timer<'d, T>,
@@ -14,14 +18,14 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> {
14 18
15impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { 19impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
16 /// Create a new PWM input driver. 20 /// Create a new PWM input driver.
17 pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl Channel1Pin<T>>, pull: Pull, freq: Hertz) -> Self { 21 pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
18 pin.set_as_af(pin.af_num(), AfType::input(pull)); 22 pin.set_as_af(pin.af_num(), AfType::input(pull));
19 23
20 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) 24 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
21 } 25 }
22 26
23 /// Create a new PWM input driver. 27 /// Create a new PWM input driver.
24 pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl Channel2Pin<T>>, pull: Pull, freq: Hertz) -> Self { 28 pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
25 pin.set_as_af(pin.af_num(), AfType::input(pull)); 29 pin.set_as_af(pin.af_num(), AfType::input(pull));
26 30
27 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) 31 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
@@ -37,6 +41,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
37 41
38 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6 42 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6
39 // or ST RM0008 (STM32F103) chapter 15.3.6 Input capture mode 43 // or ST RM0008 (STM32F103) chapter 15.3.6 Input capture mode
44 // or ST RM0440 (STM32G4) chapter 30.4.8 PWM input mode
40 inner.set_input_ti_selection(ch1, InputTISelection::Normal); 45 inner.set_input_ti_selection(ch1, InputTISelection::Normal);
41 inner.set_input_capture_mode(ch1, InputCaptureMode::Rising); 46 inner.set_input_capture_mode(ch1, InputCaptureMode::Rising);
42 47
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index f3c81667c..eabe1b22a 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -6,8 +6,9 @@ use stm32_metapac::timer::vals;
6 6
7use super::low_level::Timer; 7use super::low_level::Timer;
8pub use super::{Ch1, Ch2}; 8pub use super::{Ch1, Ch2};
9use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; 9use super::{GeneralInstance4Channel, TimerPin};
10use crate::gpio::{AfType, AnyPin, Pull}; 10use crate::gpio::{AfType, AnyPin, Pull};
11use crate::timer::TimerChannel;
11use crate::Peri; 12use crate::Peri;
12 13
13/// Counting direction 14/// Counting direction
@@ -24,26 +25,31 @@ pub struct QeiPin<'d, T, Channel> {
24 phantom: PhantomData<(T, Channel)>, 25 phantom: PhantomData<(T, Channel)>,
25} 26}
26 27
27macro_rules! channel_impl { 28impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
28 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 29 /// Create a new QEI pin instance.
29 impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { 30 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
30 #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] 31 critical_section::with(|_| {
31 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self { 32 pin.set_low();
32 critical_section::with(|_| { 33 pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
33 pin.set_low(); 34 });
34 pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); 35 QeiPin {
35 }); 36 _pin: pin.into(),
36 QeiPin { 37 phantom: PhantomData,
37 _pin: pin.into(),
38 phantom: PhantomData,
39 }
40 }
41 } 38 }
42 }; 39 }
43} 40}
44 41
45channel_impl!(new_ch1, Ch1, Channel1Pin); 42trait SealedQeiChannel: TimerChannel {}
46channel_impl!(new_ch2, Ch2, Channel2Pin); 43
44/// Marker trait for a timer channel eligible for use with QEI.
45#[expect(private_bounds)]
46pub trait QeiChannel: SealedQeiChannel {}
47
48impl QeiChannel for Ch1 {}
49impl QeiChannel for Ch2 {}
50
51impl SealedQeiChannel for Ch1 {}
52impl SealedQeiChannel for Ch2 {}
47 53
48/// Quadrature decoder driver. 54/// Quadrature decoder driver.
49pub struct Qei<'d, T: GeneralInstance4Channel> { 55pub struct Qei<'d, T: GeneralInstance4Channel> {
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index f7f433154..c04b1ab97 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -4,22 +4,13 @@ use core::marker::PhantomData;
4use core::mem::ManuallyDrop; 4use core::mem::ManuallyDrop;
5 5
6use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; 6use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
7use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel, TimerBits}; 7use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
8#[cfg(gpio_v2)] 8#[cfg(gpio_v2)]
9use crate::gpio::Pull; 9use crate::gpio::Pull;
10use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 10use crate::gpio::{AfType, AnyPin, OutputType, Speed};
11use crate::time::Hertz; 11use crate::time::Hertz;
12use crate::Peri; 12use crate::Peri;
13 13
14/// Channel 1 marker type.
15pub enum Ch1 {}
16/// Channel 2 marker type.
17pub enum Ch2 {}
18/// Channel 3 marker type.
19pub enum Ch3 {}
20/// Channel 4 marker type.
21pub enum Ch4 {}
22
23/// PWM pin wrapper. 14/// PWM pin wrapper.
24/// 15///
25/// This wraps a pin to make it usable with PWM. 16/// This wraps a pin to make it usable with PWM.
@@ -43,46 +34,37 @@ pub struct PwmPinConfig {
43 pub pull: Pull, 34 pub pull: Pull,
44} 35}
45 36
46macro_rules! channel_impl { 37impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
47 ($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => { 38 /// Create a new PWM pin instance.
48 impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { 39 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
49 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] 40 critical_section::with(|_| {
50 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, output_type: OutputType) -> Self { 41 pin.set_low();
51 critical_section::with(|_| { 42 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
52 pin.set_low(); 43 });
53 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); 44 PwmPin {
54 }); 45 _pin: pin.into(),
55 PwmPin { 46 phantom: PhantomData,
56 _pin: pin.into(),
57 phantom: PhantomData,
58 }
59 }
60
61 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")]
62 pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait<T>>, pin_config: PwmPinConfig) -> Self {
63 critical_section::with(|_| {
64 pin.set_low();
65 pin.set_as_af(
66 pin.af_num(),
67 #[cfg(gpio_v1)]
68 AfType::output(pin_config.output_type, pin_config.speed),
69 #[cfg(gpio_v2)]
70 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
71 );
72 });
73 PwmPin {
74 _pin: pin.into(),
75 phantom: PhantomData,
76 }
77 }
78 } 47 }
79 }; 48 }
80}
81 49
82channel_impl!(new_ch1, new_ch1_with_config, Ch1, Channel1Pin); 50 /// Create a new PWM pin instance with config.
83channel_impl!(new_ch2, new_ch2_with_config, Ch2, Channel2Pin); 51 pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
84channel_impl!(new_ch3, new_ch3_with_config, Ch3, Channel3Pin); 52 critical_section::with(|_| {
85channel_impl!(new_ch4, new_ch4_with_config, Ch4, Channel4Pin); 53 pin.set_low();
54 pin.set_as_af(
55 pin.af_num(),
56 #[cfg(gpio_v1)]
57 AfType::output(pin_config.output_type, pin_config.speed),
58 #[cfg(gpio_v2)]
59 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
60 );
61 });
62 PwmPin {
63 _pin: pin.into(),
64 phantom: PhantomData,
65 }
66 }
67}
86 68
87/// A single channel of a pwm, obtained from [`SimplePwm::split`], 69/// A single channel of a pwm, obtained from [`SimplePwm::split`],
88/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc. 70/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
@@ -466,107 +448,98 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
466 } 448 }
467} 449}
468 450
469macro_rules! impl_waveform_chx { 451impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
470 ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { 452 /// Generate a sequence of PWM waveform
471 impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { 453 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
472 /// Generate a sequence of PWM waveform 454 use crate::pac::timer::vals::Ccds;
473 pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch<T>>, duty: &[u16]) { 455
474 use crate::pac::timer::vals::Ccds; 456 #[allow(clippy::let_unit_value)] // eg. stm32f334
457 let req = dma.request();
475 458
476 #[allow(clippy::let_unit_value)] // eg. stm32f334 459 let cc_channel = C::CHANNEL;
477 let req = dma.request();
478 460
479 let cc_channel = Channel::$cc_ch; 461 let original_duty_state = self.channel(cc_channel).current_duty_cycle();
462 let original_enable_state = self.channel(cc_channel).is_enabled();
463 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
464 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
480 465
481 let original_duty_state = self.channel(cc_channel).current_duty_cycle(); 466 // redirect CC DMA request onto Update Event
482 let original_enable_state = self.channel(cc_channel).is_enabled(); 467 if !original_cc_dma_on_update {
483 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; 468 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
484 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); 469 }
485 470
486 // redirect CC DMA request onto Update Event 471 if !original_cc_dma_enabled {
487 if !original_cc_dma_on_update { 472 self.inner.set_cc_dma_enable_state(cc_channel, true);
488 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) 473 }
489 }
490 474
491 if !original_cc_dma_enabled { 475 if !original_enable_state {
492 self.inner.set_cc_dma_enable_state(cc_channel, true); 476 self.channel(cc_channel).enable();
493 } 477 }
494 478
495 if !original_enable_state { 479 unsafe {
496 self.channel(cc_channel).enable(); 480 #[cfg(not(any(bdma, gpdma)))]
497 } 481 use crate::dma::{Burst, FifoThreshold};
482 use crate::dma::{Transfer, TransferOptions};
498 483
499 unsafe { 484 let dma_transfer_option = TransferOptions {
485 #[cfg(not(any(bdma, gpdma)))]
486 fifo_threshold: Some(FifoThreshold::Full),
487 #[cfg(not(any(bdma, gpdma)))]
488 mburst: Burst::Incr8,
489 ..Default::default()
490 };
491
492 match self.inner.bits() {
493 TimerBits::Bits16 => {
494 Transfer::new_write(
495 dma,
496 req,
497 duty,
498 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
499 dma_transfer_option,
500 )
501 .await
502 }
503 #[cfg(not(any(stm32l0)))]
504 TimerBits::Bits32 => {
500 #[cfg(not(any(bdma, gpdma)))] 505 #[cfg(not(any(bdma, gpdma)))]
501 use crate::dma::{Burst, FifoThreshold}; 506 panic!("unsupported timer bits");
502 use crate::dma::{Transfer, TransferOptions}; 507
503 508 #[cfg(any(bdma, gpdma))]
504 let dma_transfer_option = TransferOptions { 509 Transfer::new_write(
505 #[cfg(not(any(bdma, gpdma)))] 510 dma,
506 fifo_threshold: Some(FifoThreshold::Full), 511 req,
507 #[cfg(not(any(bdma, gpdma)))] 512 duty,
508 mburst: Burst::Incr8, 513 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
509 ..Default::default() 514 dma_transfer_option,
510 }; 515 )
511 516 .await
512 match self.inner.bits() {
513 TimerBits::Bits16 => {
514 Transfer::new_write(
515 dma,
516 req,
517 duty,
518 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
519 dma_transfer_option,
520 )
521 .await
522 }
523 #[cfg(not(any(stm32l0)))]
524 TimerBits::Bits32 => {
525 #[cfg(not(any(bdma, gpdma)))]
526 panic!("unsupported timer bits");
527
528 #[cfg(any(bdma, gpdma))]
529 Transfer::new_write(
530 dma,
531 req,
532 duty,
533 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
534 dma_transfer_option,
535 )
536 .await
537 }
538 };
539 };
540
541 // restore output compare state
542 if !original_enable_state {
543 self.channel(cc_channel).disable();
544 } 517 }
518 };
519 };
520
521 // restore output compare state
522 if !original_enable_state {
523 self.channel(cc_channel).disable();
524 }
545 525
546 self.channel(cc_channel).set_duty_cycle(original_duty_state); 526 self.channel(cc_channel).set_duty_cycle(original_duty_state);
547 527
548 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, 528 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
549 // this can almost always trigger a DMA FIFO error. 529 // this can almost always trigger a DMA FIFO error.
550 // 530 //
551 // optional TODO: 531 // optional TODO:
552 // clean FEIF after disable UDE 532 // clean FEIF after disable UDE
553 if !original_cc_dma_enabled { 533 if !original_cc_dma_enabled {
554 self.inner.set_cc_dma_enable_state(cc_channel, false); 534 self.inner.set_cc_dma_enable_state(cc_channel, false);
555 } 535 }
556 536
557 if !original_cc_dma_on_update { 537 if !original_cc_dma_on_update {
558 self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) 538 self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
559 }
560 }
561 } 539 }
562 }; 540 }
563} 541}
564 542
565impl_waveform_chx!(waveform_ch1, Ch1Dma, Ch1);
566impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
567impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
568impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
569
570impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { 543impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
571 type Error = core::convert::Infallible; 544 type Error = core::convert::Infallible;
572} 545}
diff --git a/embassy-stm32/src/tsc/acquisition_banks.rs b/embassy-stm32/src/tsc/acquisition_banks.rs
index 6791ef6c1..7d6442b48 100644
--- a/embassy-stm32/src/tsc/acquisition_banks.rs
+++ b/embassy-stm32/src/tsc/acquisition_banks.rs
@@ -32,7 +32,7 @@ impl AcquisitionBankPins {
32 /// Returns an iterator over the pins in this acquisition bank. 32 /// Returns an iterator over the pins in this acquisition bank.
33 /// 33 ///
34 /// This method allows for easy traversal of all configured pins in the bank. 34 /// This method allows for easy traversal of all configured pins in the bank.
35 pub fn iter(&self) -> AcquisitionBankPinsIterator { 35 pub fn iter(&self) -> AcquisitionBankPinsIterator<'_> {
36 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) 36 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self))
37 } 37 }
38} 38}
@@ -90,7 +90,7 @@ impl<'a> Iterator for AcquisitionBankPinsIterator<'a> {
90 90
91impl AcquisitionBankPins { 91impl AcquisitionBankPins {
92 /// Returns an iterator over the available pins in the bank 92 /// Returns an iterator over the available pins in the bank
93 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { 93 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator<'_> {
94 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self)) 94 AcquisitionBankPinsIterator(AcquisitionBankIterator::new(self))
95 } 95 }
96} 96}
@@ -107,7 +107,7 @@ pub struct AcquisitionBank {
107 107
108impl AcquisitionBank { 108impl AcquisitionBank {
109 /// Returns an iterator over the available pins in the bank. 109 /// Returns an iterator over the available pins in the bank.
110 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator { 110 pub fn pins_iterator(&self) -> AcquisitionBankPinsIterator<'_> {
111 self.pins.pins_iterator() 111 self.pins.pins_iterator()
112 } 112 }
113 113
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 73ab46404..729440c46 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -87,6 +87,8 @@ unsafe fn on_interrupt(r: Regs, state: &'static State) {
87 87
88 r.cr1().modify(|w| { 88 r.cr1().modify(|w| {
89 w.set_tcie(false); 89 w.set_tcie(false);
90 // Reenable receiver for half-duplex if it was disabled
91 w.set_re(true);
90 }); 92 });
91 93
92 state.tx_done.store(true, Ordering::Release); 94 state.tx_done.store(true, Ordering::Release);
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index b3f8bc00c..5bece6d66 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -550,6 +550,20 @@ impl<'d, M: Mode> UartTx<'d, M> {
550 reconfigure(self.info, self.kernel_clock, config) 550 reconfigure(self.info, self.kernel_clock, config)
551 } 551 }
552 552
553 /// Write a single u8 if there is tx empty, otherwise return WouldBlock
554 pub(crate) fn nb_write(&mut self, byte: u8) -> Result<(), nb::Error<Error>> {
555 let r = self.info.regs;
556 let sr = sr(r).read();
557 if sr.txe() {
558 unsafe {
559 tdr(r).write_volatile(byte);
560 }
561 Ok(())
562 } else {
563 Err(nb::Error::WouldBlock)
564 }
565 }
566
553 /// Perform a blocking UART write 567 /// Perform a blocking UART write
554 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 568 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
555 let r = self.info.regs; 569 let r = self.info.regs;
@@ -637,7 +651,7 @@ pub fn send_break(regs: &Regs) {
637/// In case of readback, keep Receiver enabled 651/// In case of readback, keep Receiver enabled
638fn half_duplex_set_rx_tx_before_write(r: &Regs, enable_readback: bool) { 652fn half_duplex_set_rx_tx_before_write(r: &Regs, enable_readback: bool) {
639 let mut cr1 = r.cr1().read(); 653 let mut cr1 = r.cr1().read();
640 if r.cr3().read().hdsel() && !cr1.te() { 654 if r.cr3().read().hdsel() {
641 cr1.set_te(true); 655 cr1.set_te(true);
642 cr1.set_re(enable_readback); 656 cr1.set_re(enable_readback);
643 r.cr1().write_value(cr1); 657 r.cr1().write_value(cr1);
@@ -1864,7 +1878,7 @@ impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> {
1864 1878
1865impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> { 1879impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> {
1866 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { 1880 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
1867 self.blocking_write(&[char]).map_err(nb::Error::Other) 1881 self.nb_write(char)
1868 } 1882 }
1869 1883
1870 fn flush(&mut self) -> nb::Result<(), Self::Error> { 1884 fn flush(&mut self) -> nb::Result<(), Self::Error> {
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index ae5963420..692897b59 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -15,7 +15,7 @@ fn common_init<T: Instance>() {
15 let freq = T::frequency(); 15 let freq = T::frequency();
16 16
17 // On the H7RS, the USBPHYC embeds a PLL accepting one of the input frequencies listed below and providing 48MHz to OTG_FS and 60MHz to OTG_HS internally 17 // On the H7RS, the USBPHYC embeds a PLL accepting one of the input frequencies listed below and providing 48MHz to OTG_FS and 60MHz to OTG_HS internally
18 #[cfg(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs)))] 18 #[cfg(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs)))]
19 if ![16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000].contains(&freq.0) { 19 if ![16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000].contains(&freq.0) {
20 panic!( 20 panic!(
21 "USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but is {} Hz. Please double-check your RCC settings.", 21 "USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but is {} Hz. Please double-check your RCC settings.",
@@ -25,7 +25,7 @@ fn common_init<T: Instance>() {
25 // Check frequency is within the 0.25% tolerance allowed by the spec. 25 // Check frequency is within the 0.25% tolerance allowed by the spec.
26 // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user 26 // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user
27 // has tight clock restrictions due to something else (like audio). 27 // has tight clock restrictions due to something else (like audio).
28 #[cfg(not(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs))))] 28 #[cfg(not(any(stm32h7rs, all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs))))]
29 if freq.0.abs_diff(48_000_000) > 120_000 { 29 if freq.0.abs_diff(48_000_000) > 120_000 {
30 panic!( 30 panic!(
31 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.", 31 "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
@@ -102,6 +102,30 @@ fn common_init<T: Instance>() {
102 } 102 }
103 } 103 }
104 104
105 #[cfg(stm32wba)]
106 {
107 // Enable USB power
108 critical_section::with(|_| {
109 crate::pac::PWR.svmcr().modify(|w| {
110 w.set_usv(crate::pac::pwr::vals::Usv::B_0X1);
111 // w.set_uvmen(true);
112 })
113 });
114
115 // Wait for USB power to stabilize
116 while !crate::pac::PWR.vosr().read().vdd11usbrdy() {}
117
118 // Now set up transceiver power if it's a OTG-HS
119 #[cfg(peri_usb_otg_hs)]
120 {
121 crate::pac::PWR.vosr().modify(|w| {
122 w.set_usbpwren(true);
123 w.set_usbboosten(true);
124 });
125 while !crate::pac::PWR.vosr().read().usbboostrdy() {}
126 }
127 }
128
105 T::Interrupt::unpend(); 129 T::Interrupt::unpend();
106 unsafe { T::Interrupt::enable() }; 130 unsafe { T::Interrupt::enable() };
107 131
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 590d1a427..b074cfa1b 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -105,7 +105,7 @@ impl<'d, T: Instance> Driver<'d, T> {
105 config: Config, 105 config: Config,
106 ) -> Self { 106 ) -> Self {
107 // For STM32U5 High speed pins need to be left in analog mode 107 // For STM32U5 High speed pins need to be left in analog mode
108 #[cfg(not(all(stm32u5, peri_usb_otg_hs)))] 108 #[cfg(not(any(all(stm32u5, peri_usb_otg_hs), all(stm32wba, peri_usb_otg_hs))))]
109 { 109 {
110 _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 110 _dp.set_as_af(_dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
111 _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 111 _dm.set_as_af(_dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
@@ -231,19 +231,23 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
231 fn alloc_endpoint_in( 231 fn alloc_endpoint_in(
232 &mut self, 232 &mut self,
233 ep_type: EndpointType, 233 ep_type: EndpointType,
234 ep_addr: Option<EndpointAddress>,
234 max_packet_size: u16, 235 max_packet_size: u16,
235 interval_ms: u8, 236 interval_ms: u8,
236 ) -> Result<Self::EndpointIn, EndpointAllocError> { 237 ) -> Result<Self::EndpointIn, EndpointAllocError> {
237 self.inner.alloc_endpoint_in(ep_type, max_packet_size, interval_ms) 238 self.inner
239 .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
238 } 240 }
239 241
240 fn alloc_endpoint_out( 242 fn alloc_endpoint_out(
241 &mut self, 243 &mut self,
242 ep_type: EndpointType, 244 ep_type: EndpointType,
245 ep_addr: Option<EndpointAddress>,
243 max_packet_size: u16, 246 max_packet_size: u16,
244 interval_ms: u8, 247 interval_ms: u8,
245 ) -> Result<Self::EndpointOut, EndpointAllocError> { 248 ) -> Result<Self::EndpointOut, EndpointAllocError> {
246 self.inner.alloc_endpoint_out(ep_type, max_packet_size, interval_ms) 249 self.inner
250 .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
247 } 251 }
248 252
249 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 253 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
@@ -323,6 +327,20 @@ impl<'d, T: Instance> Bus<'d, T> {
323 }); 327 });
324 } 328 }
325 329
330 #[cfg(all(stm32wba, peri_usb_otg_hs))]
331 {
332 crate::pac::SYSCFG.otghsphycr().modify(|w| {
333 w.set_en(true);
334 });
335
336 critical_section::with(|_| {
337 crate::pac::RCC.ahb2enr().modify(|w| {
338 w.set_usb_otg_hsen(true);
339 w.set_otghsphyen(true);
340 });
341 });
342 }
343
326 let r = T::regs(); 344 let r = T::regs();
327 let core_id = r.cid().read().0; 345 let core_id = r.cid().read().0;
328 trace!("Core id {:08x}", core_id); 346 trace!("Core id {:08x}", core_id);
@@ -464,6 +482,7 @@ foreach_interrupt!(
464 stm32f7, 482 stm32f7,
465 stm32l4, 483 stm32l4,
466 stm32u5, 484 stm32u5,
485 stm32wba,
467 ))] { 486 ))] {
468 const FIFO_DEPTH_WORDS: u16 = 320; 487 const FIFO_DEPTH_WORDS: u16 = 320;
469 const ENDPOINT_COUNT: usize = 6; 488 const ENDPOINT_COUNT: usize = 6;
@@ -473,7 +492,7 @@ foreach_interrupt!(
473 } else if #[cfg(any(stm32h7, stm32h7rs))] { 492 } else if #[cfg(any(stm32h7, stm32h7rs))] {
474 const FIFO_DEPTH_WORDS: u16 = 1024; 493 const FIFO_DEPTH_WORDS: u16 = 1024;
475 const ENDPOINT_COUNT: usize = 9; 494 const ENDPOINT_COUNT: usize = 9;
476 } else if #[cfg(stm32u5)] { 495 } else if #[cfg(any(stm32wba, stm32u5))] {
477 const FIFO_DEPTH_WORDS: u16 = 320; 496 const FIFO_DEPTH_WORDS: u16 = 320;
478 const ENDPOINT_COUNT: usize = 6; 497 const ENDPOINT_COUNT: usize = 6;
479 } else { 498 } else {
@@ -523,7 +542,7 @@ foreach_interrupt!(
523 ))] { 542 ))] {
524 const FIFO_DEPTH_WORDS: u16 = 1024; 543 const FIFO_DEPTH_WORDS: u16 = 1024;
525 const ENDPOINT_COUNT: usize = 9; 544 const ENDPOINT_COUNT: usize = 9;
526 } else if #[cfg(stm32u5)] { 545 } else if #[cfg(any(stm32u5, stm32wba))] {
527 const FIFO_DEPTH_WORDS: u16 = 1024; 546 const FIFO_DEPTH_WORDS: u16 = 1024;
528 const ENDPOINT_COUNT: usize = 9; 547 const ENDPOINT_COUNT: usize = 9;
529 } else { 548 } else {
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 3e8e74a1f..92c1601cc 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -359,9 +359,38 @@ impl<'d, T: Instance> Driver<'d, T> {
359 addr 359 addr
360 } 360 }
361 361
362 fn is_endpoint_available<D: Dir>(&self, index: usize, ep_type: EndpointType) -> bool {
363 if index == 0 && ep_type != EndpointType::Control {
364 return false; // EP0 is reserved for control
365 }
366
367 let ep = match self.alloc.get(index) {
368 Some(ep) => ep,
369 None => return false,
370 };
371
372 let used = ep.used_out || ep.used_in;
373
374 if used && ep.ep_type == EndpointType::Isochronous {
375 // Isochronous endpoints are always double-buffered.
376 // Their corresponding endpoint/channel registers are forced to be unidirectional.
377 // Do not reuse this index.
378 // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation.
379 return false;
380 }
381
382 let used_dir = match D::dir() {
383 Direction::Out => ep.used_out,
384 Direction::In => ep.used_in,
385 };
386
387 !used || (ep.ep_type == ep_type && !used_dir)
388 }
389
362 fn alloc_endpoint<D: Dir>( 390 fn alloc_endpoint<D: Dir>(
363 &mut self, 391 &mut self,
364 ep_type: EndpointType, 392 ep_type: EndpointType,
393 ep_addr: Option<EndpointAddress>,
365 max_packet_size: u16, 394 max_packet_size: u16,
366 interval_ms: u8, 395 interval_ms: u8,
367 ) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> { 396 ) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
@@ -373,28 +402,17 @@ impl<'d, T: Instance> Driver<'d, T> {
373 D::dir() 402 D::dir()
374 ); 403 );
375 404
376 let index = self.alloc.iter_mut().enumerate().find(|(i, ep)| { 405 let index = if let Some(addr) = ep_addr {
377 if *i == 0 && ep_type != EndpointType::Control { 406 // Use the specified endpoint address
378 return false; // reserved for control pipe 407 self.is_endpoint_available::<D>(addr.index(), ep_type)
379 } 408 .then_some(addr.index())
380 let used = ep.used_out || ep.used_in; 409 } else {
381 if used && (ep.ep_type == EndpointType::Isochronous) { 410 // Find any available endpoint
382 // Isochronous endpoints are always double-buffered. 411 (0..self.alloc.len()).find(|&i| self.is_endpoint_available::<D>(i, ep_type))
383 // Their corresponding endpoint/channel registers are forced to be unidirectional. 412 };
384 // Do not reuse this index.
385 // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation.
386 return false;
387 }
388
389 let used_dir = match D::dir() {
390 Direction::Out => ep.used_out,
391 Direction::In => ep.used_in,
392 };
393 !used || (ep.ep_type == ep_type && !used_dir)
394 });
395 413
396 let (index, ep) = match index { 414 let (index, ep) = match index {
397 Some(x) => x, 415 Some(i) => (i, &mut self.alloc[i]),
398 None => return Err(EndpointAllocError), 416 None => return Err(EndpointAllocError),
399 }; 417 };
400 418
@@ -479,27 +497,29 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
479 fn alloc_endpoint_in( 497 fn alloc_endpoint_in(
480 &mut self, 498 &mut self,
481 ep_type: EndpointType, 499 ep_type: EndpointType,
500 ep_addr: Option<EndpointAddress>,
482 max_packet_size: u16, 501 max_packet_size: u16,
483 interval_ms: u8, 502 interval_ms: u8,
484 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { 503 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
485 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 504 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
486 } 505 }
487 506
488 fn alloc_endpoint_out( 507 fn alloc_endpoint_out(
489 &mut self, 508 &mut self,
490 ep_type: EndpointType, 509 ep_type: EndpointType,
510 ep_addr: Option<EndpointAddress>,
491 max_packet_size: u16, 511 max_packet_size: u16,
492 interval_ms: u8, 512 interval_ms: u8,
493 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { 513 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
494 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 514 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
495 } 515 }
496 516
497 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 517 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
498 let ep_out = self 518 let ep_out = self
499 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) 519 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
500 .unwrap(); 520 .unwrap();
501 let ep_in = self 521 let ep_in = self
502 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) 522 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
503 .unwrap(); 523 .unwrap();
504 assert_eq!(ep_out.info.addr.index(), 0); 524 assert_eq!(ep_out.info.addr.index(), 0);
505 assert_eq!(ep_in.info.addr.index(), 0); 525 assert_eq!(ep_in.info.addr.index(), 0);