aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh6
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/build.rs125
-rw-r--r--embassy-stm32/src/can/bxcan/mod.rs12
-rw-r--r--embassy-stm32/src/eth/mod.rs32
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs54
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs50
-rw-r--r--embassy-stm32/src/gpio.rs11
-rw-r--r--embassy-stm32/src/i2c/mod.rs16
-rw-r--r--embassy-stm32/src/i2s.rs46
-rw-r--r--embassy-stm32/src/macros.rs63
-rw-r--r--embassy-stm32/src/spi/mod.rs62
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs34
-rw-r--r--embassy-stm32/src/timer/input_capture.rs21
-rw-r--r--embassy-stm32/src/timer/mod.rs31
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs10
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs4
-rw-r--r--embassy-stm32/src/timer/qei.rs12
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs23
-rw-r--r--embassy-stm32/src/usart/buffered.rs48
-rw-r--r--embassy-stm32/src/usart/mod.rs116
-rw-r--r--tests/stm32/Cargo.toml12
-rw-r--r--tests/stm32/src/bin/afio.rs1156
-rw-r--r--tests/stm32/src/common.rs2
24 files changed, 1679 insertions, 268 deletions
diff --git a/ci.sh b/ci.sh
index e1197f397..50fb3e13d 100755
--- a/ci.sh
+++ b/ci.sh
@@ -311,7 +311,9 @@ cargo batch \
311 --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \ 311 --- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \
312 --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \ 312 --- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \
313 --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \ 313 --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --artifact-dir out/examples/wasm \
314 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f100rd --artifact-dir out/tests/stm32f100rd \
314 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \ 315 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --artifact-dir out/tests/stm32f103c8 \
316 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f107vc --artifact-dir out/tests/stm32f107vc \
315 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \ 317 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \
316 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \ 318 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \
317 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \ 319 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re --artifact-dir out/tests/stm32g491re \
@@ -398,8 +400,10 @@ rm out/tests/pimoroni-pico-plus-2/pwm
398rm out/tests/rpi-pico/pwm 400rm out/tests/rpi-pico/pwm
399rm out/tests/rpi-pico/cyw43-perf 401rm out/tests/rpi-pico/cyw43-perf
400 402
401# tests are implemented but the HIL test farm doesn't actually have this board yet 403# tests are implemented but the HIL test farm doesn't actually have these boards, yet
402rm -rf out/tests/stm32c071rb 404rm -rf out/tests/stm32c071rb
405rm -rf out/tests/stm32f100rd
406rm -rf out/tests/stm32f107vc
403 407
404if [[ -z "${TELEPROBE_TOKEN-}" ]]; then 408if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
405 echo No teleprobe token found, skipping running HIL tests 409 echo No teleprobe token found, skipping running HIL tests
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index a473834dd..db0c1e89c 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
32- fix: Fix stm32h7rs init when using external flash via XSPI 32- fix: Fix stm32h7rs init when using external flash via XSPI
33- feat: Add Adc::new_with_clock() to configure analog clock 33- feat: Add Adc::new_with_clock() to configure analog clock
34- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923)) 34- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923))
35- feat: Added support for STM32F1 peripheral pin remapping (AFIO) ([#4430](https://github.com/embassy-rs/embassy/pull/4430))
35 36
36## 0.3.0 - 2025-08-12 37## 0.3.0 - 2025-08-12
37 38
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index b731012c6..f55e1e0c9 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1391,9 +1391,60 @@ fn main() {
1391 }) 1391 })
1392 } 1392 }
1393 1393
1394 g.extend(quote! { 1394 let pin_trait_impl = p
1395 pin_trait_impl!(#tr, #peri, #pin_name, #af); 1395 .afio
1396 }) 1396 .as_ref()
1397 .and_then(|afio| {
1398 if p.name.starts_with("TIM") {
1399 // timers are handled by timer_afio_impl!()
1400 return None;
1401 }
1402
1403 let values = afio
1404 .values
1405 .iter()
1406 .filter(|v| v.pins.contains(&pin.pin))
1407 .map(|v| v.value)
1408 .collect::<Vec<_>>();
1409
1410 if values.is_empty() {
1411 None
1412 } else {
1413 let setter = format_ident!("set_{}", afio.field.to_lowercase());
1414 let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) {
1415 let values = values.iter().map(|&v| v > 0);
1416 quote!(AfioRemapBool, [#(#values),*])
1417 } else {
1418 quote!(AfioRemap, [#(#values),*])
1419 };
1420
1421 Some(quote! {
1422 pin_trait_afio_impl!(#tr, #peri, #pin_name, {#setter, #type_and_values});
1423 })
1424 }
1425 })
1426 .unwrap_or_else(|| {
1427 let peripherals_with_afio = [
1428 "CAN",
1429 "CEC",
1430 "ETH",
1431 "I2C",
1432 "SPI",
1433 "SUBGHZSPI",
1434 "USART",
1435 "UART",
1436 "LPUART",
1437 ];
1438 let af_or_not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) {
1439 quote!(0, crate::gpio::AfioRemapNotApplicable)
1440 } else {
1441 quote!(#af)
1442 };
1443
1444 quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af_or_not_applicable);)
1445 });
1446
1447 g.extend(pin_trait_impl);
1397 } 1448 }
1398 1449
1399 // ADC is special 1450 // ADC is special
@@ -1588,17 +1639,7 @@ fn main() {
1588 let register = format_ident!("{}", remap_info.register.to_lowercase()); 1639 let register = format_ident!("{}", remap_info.register.to_lowercase());
1589 let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); 1640 let setter = format_ident!("set_{}", remap_info.field.to_lowercase());
1590 1641
1591 let field_metadata = METADATA 1642 let value = if is_bool_field("SYSCFG", &remap_info.register, &remap_info.field) {
1592 .peripherals
1593 .iter()
1594 .filter(|p| p.name == "SYSCFG")
1595 .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter())
1596 .filter(|f| f.name.eq_ignore_ascii_case(remap_info.register))
1597 .flat_map(|f| f.fields.iter())
1598 .find(|f| f.name.eq_ignore_ascii_case(remap_info.field))
1599 .unwrap();
1600
1601 let value = if field_metadata.bit_size == 1 {
1602 let bool_value = format_ident!("{}", remap_info.value > 0); 1643 let bool_value = format_ident!("{}", remap_info.value > 0);
1603 quote!(#bool_value) 1644 quote!(#bool_value)
1604 } else { 1645 } else {
@@ -1929,6 +1970,48 @@ fn main() {
1929 }); 1970 });
1930 1971
1931 // ======== 1972 // ========
1973 // Generate timer AFIO impls
1974
1975 for p in METADATA.peripherals {
1976 if p.name.starts_with("TIM") {
1977 let pname = format_ident!("{}", p.name);
1978 let afio = if let Some(afio) = &p.afio {
1979 let register = format_ident!("{}", afio.register.to_lowercase());
1980 let setter = format_ident!("set_{}", afio.field.to_lowercase());
1981
1982 let swj_cfg = if afio.register == "MAPR" {
1983 quote!(w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);)
1984 } else {
1985 quote!()
1986 };
1987 let bool_eval = if is_bool_field("AFIO", &afio.register, &afio.field) {
1988 quote!(> 0)
1989 } else {
1990 quote!()
1991 };
1992
1993 let values = afio.values.iter().map(|v| {
1994 let mapr_value = v.value;
1995 let pin = v.pins.iter().map(|p| {
1996 let port_num = p.chars().nth(1).unwrap() as u8 - b'A';
1997 let pin_num = p[2..].parse::<u8>().unwrap();
1998 port_num * 16 + pin_num
1999 });
2000 quote!(#mapr_value, [#(#pin),*])
2001 });
2002
2003 quote! {
2004 , |v| crate::pac::AFIO.#register().modify(|w| { #swj_cfg w.#setter(v #bool_eval); }), #({#values}),*
2005 }
2006 } else {
2007 quote!()
2008 };
2009
2010 g.extend(quote!(timer_afio_impl!(#pname #afio);));
2011 }
2012 }
2013
2014 // ========
1932 // Generate gpio_block() function 2015 // Generate gpio_block() function
1933 2016
1934 let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as usize; 2017 let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as usize;
@@ -2300,3 +2383,17 @@ fn gcd(a: u32, b: u32) -> u32 {
2300 } 2383 }
2301 gcd(b, a % b) 2384 gcd(b, a % b)
2302} 2385}
2386
2387fn is_bool_field(peripheral: &str, register: &str, field: &str) -> bool {
2388 let field_metadata = METADATA
2389 .peripherals
2390 .iter()
2391 .filter(|p| p.name == peripheral)
2392 .flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter())
2393 .filter(|f| f.name.eq_ignore_ascii_case(register))
2394 .flat_map(|f| f.fields.iter())
2395 .find(|f| f.name.eq_ignore_ascii_case(field))
2396 .unwrap();
2397
2398 field_metadata.bit_size == 1
2399}
diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs
index 4c0795a2a..9ebfeb42f 100644
--- a/embassy-stm32/src/can/bxcan/mod.rs
+++ b/embassy-stm32/src/can/bxcan/mod.rs
@@ -181,10 +181,10 @@ pub enum TryWriteError {
181impl<'d> Can<'d> { 181impl<'d> Can<'d> {
182 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. 182 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
183 /// You must call [Can::enable_non_blocking] to use the peripheral. 183 /// You must call [Can::enable_non_blocking] to use the peripheral.
184 pub fn new<T: Instance>( 184 pub fn new<T: Instance, A>(
185 _peri: Peri<'d, T>, 185 _peri: Peri<'d, T>,
186 rx: Peri<'d, impl RxPin<T>>, 186 rx: Peri<'d, impl RxPin<T, A>>,
187 tx: Peri<'d, impl TxPin<T>>, 187 tx: Peri<'d, impl TxPin<T, A>>,
188 _irqs: impl interrupt::typelevel::Binding<T::TXInterrupt, TxInterruptHandler<T>> 188 _irqs: impl interrupt::typelevel::Binding<T::TXInterrupt, TxInterruptHandler<T>>
189 + interrupt::typelevel::Binding<T::RX0Interrupt, Rx0InterruptHandler<T>> 189 + interrupt::typelevel::Binding<T::RX0Interrupt, Rx0InterruptHandler<T>>
190 + interrupt::typelevel::Binding<T::RX1Interrupt, Rx1InterruptHandler<T>> 190 + interrupt::typelevel::Binding<T::RX1Interrupt, Rx1InterruptHandler<T>>
@@ -195,6 +195,8 @@ impl<'d> Can<'d> {
195 let regs = &T::info().regs; 195 let regs = &T::info().regs;
196 196
197 rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); 197 rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
198 #[cfg(afio)]
199 rx.afio_remap();
198 tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 200 tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
199 201
200 rcc::enable_and_reset::<T>(); 202 rcc::enable_and_reset::<T>();
@@ -1218,8 +1220,8 @@ foreach_peripheral!(
1218 }; 1220 };
1219); 1221);
1220 1222
1221pin_trait!(RxPin, Instance); 1223pin_trait!(RxPin, Instance, @A);
1222pin_trait!(TxPin, Instance); 1224pin_trait!(TxPin, Instance, @A);
1223 1225
1224trait Index { 1226trait Index {
1225 fn index(&self) -> usize; 1227 fn index(&self) -> usize;
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 97d7b4347..10b3a0517 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -209,19 +209,19 @@ impl SealedInstance for crate::peripherals::ETH {
209} 209}
210impl Instance for crate::peripherals::ETH {} 210impl Instance for crate::peripherals::ETH {}
211 211
212pin_trait!(RXClkPin, Instance); 212pin_trait!(RXClkPin, Instance, @A);
213pin_trait!(TXClkPin, Instance); 213pin_trait!(TXClkPin, Instance, @A);
214pin_trait!(RefClkPin, Instance); 214pin_trait!(RefClkPin, Instance, @A);
215pin_trait!(MDIOPin, Instance); 215pin_trait!(MDIOPin, Instance, @A);
216pin_trait!(MDCPin, Instance); 216pin_trait!(MDCPin, Instance, @A);
217pin_trait!(RXDVPin, Instance); 217pin_trait!(RXDVPin, Instance, @A);
218pin_trait!(CRSPin, Instance); 218pin_trait!(CRSPin, Instance, @A);
219pin_trait!(RXD0Pin, Instance); 219pin_trait!(RXD0Pin, Instance, @A);
220pin_trait!(RXD1Pin, Instance); 220pin_trait!(RXD1Pin, Instance, @A);
221pin_trait!(RXD2Pin, Instance); 221pin_trait!(RXD2Pin, Instance, @A);
222pin_trait!(RXD3Pin, Instance); 222pin_trait!(RXD3Pin, Instance, @A);
223pin_trait!(TXD0Pin, Instance); 223pin_trait!(TXD0Pin, Instance, @A);
224pin_trait!(TXD1Pin, Instance); 224pin_trait!(TXD1Pin, Instance, @A);
225pin_trait!(TXD2Pin, Instance); 225pin_trait!(TXD2Pin, Instance, @A);
226pin_trait!(TXD3Pin, Instance); 226pin_trait!(TXD3Pin, Instance, @A);
227pin_trait!(TXEnPin, Instance); 227pin_trait!(TXEnPin, Instance, @A);
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index b9746231f..45be65c5f 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -99,19 +99,19 @@ macro_rules! config_pins {
99 99
100impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { 100impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
101 /// safety: the returned instance is not leak-safe 101 /// safety: the returned instance is not leak-safe
102 pub fn new<const TX: usize, const RX: usize>( 102 pub fn new<const TX: usize, const RX: usize, A>(
103 queue: &'d mut PacketQueue<TX, RX>, 103 queue: &'d mut PacketQueue<TX, RX>,
104 peri: Peri<'d, T>, 104 peri: Peri<'d, T>,
105 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 105 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
106 ref_clk: Peri<'d, impl RefClkPin<T>>, 106 ref_clk: Peri<'d, impl RefClkPin<T, A>>,
107 mdio: Peri<'d, impl MDIOPin<T>>, 107 mdio: Peri<'d, impl MDIOPin<T, A>>,
108 mdc: Peri<'d, impl MDCPin<T>>, 108 mdc: Peri<'d, impl MDCPin<T, A>>,
109 crs: Peri<'d, impl CRSPin<T>>, 109 crs: Peri<'d, impl CRSPin<T, A>>,
110 rx_d0: Peri<'d, impl RXD0Pin<T>>, 110 rx_d0: Peri<'d, impl RXD0Pin<T, A>>,
111 rx_d1: Peri<'d, impl RXD1Pin<T>>, 111 rx_d1: Peri<'d, impl RXD1Pin<T, A>>,
112 tx_d0: Peri<'d, impl TXD0Pin<T>>, 112 tx_d0: Peri<'d, impl TXD0Pin<T, A>>,
113 tx_d1: Peri<'d, impl TXD1Pin<T>>, 113 tx_d1: Peri<'d, impl TXD1Pin<T, A>>,
114 tx_en: Peri<'d, impl TXEnPin<T>>, 114 tx_en: Peri<'d, impl TXEnPin<T, A>>,
115 phy: P, 115 phy: P,
116 mac_addr: [u8; 6], 116 mac_addr: [u8; 6],
117 ) -> Self { 117 ) -> Self {
@@ -150,6 +150,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
150 { 150 {
151 config_in_pins!(ref_clk, rx_d0, rx_d1); 151 config_in_pins!(ref_clk, rx_d0, rx_d1);
152 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en); 152 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_en);
153 #[cfg(afio)]
154 rx_d0.afio_remap();
153 } 155 }
154 156
155 #[cfg(any(eth_v1b, eth_v1c))] 157 #[cfg(any(eth_v1b, eth_v1c))]
@@ -289,24 +291,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
289 } 291 }
290 292
291 /// Create a new MII ethernet driver using 14 pins. 293 /// Create a new MII ethernet driver using 14 pins.
292 pub fn new_mii<const TX: usize, const RX: usize>( 294 pub fn new_mii<const TX: usize, const RX: usize, A>(
293 queue: &'d mut PacketQueue<TX, RX>, 295 queue: &'d mut PacketQueue<TX, RX>,
294 peri: Peri<'d, T>, 296 peri: Peri<'d, T>,
295 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 297 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
296 rx_clk: Peri<'d, impl RXClkPin<T>>, 298 rx_clk: Peri<'d, impl RXClkPin<T, A>>,
297 tx_clk: Peri<'d, impl TXClkPin<T>>, 299 tx_clk: Peri<'d, impl TXClkPin<T, A>>,
298 mdio: Peri<'d, impl MDIOPin<T>>, 300 mdio: Peri<'d, impl MDIOPin<T, A>>,
299 mdc: Peri<'d, impl MDCPin<T>>, 301 mdc: Peri<'d, impl MDCPin<T, A>>,
300 rxdv: Peri<'d, impl RXDVPin<T>>, 302 rxdv: Peri<'d, impl RXDVPin<T, A>>,
301 rx_d0: Peri<'d, impl RXD0Pin<T>>, 303 rx_d0: Peri<'d, impl RXD0Pin<T, A>>,
302 rx_d1: Peri<'d, impl RXD1Pin<T>>, 304 rx_d1: Peri<'d, impl RXD1Pin<T, A>>,
303 rx_d2: Peri<'d, impl RXD2Pin<T>>, 305 rx_d2: Peri<'d, impl RXD2Pin<T, A>>,
304 rx_d3: Peri<'d, impl RXD3Pin<T>>, 306 rx_d3: Peri<'d, impl RXD3Pin<T, A>>,
305 tx_d0: Peri<'d, impl TXD0Pin<T>>, 307 tx_d0: Peri<'d, impl TXD0Pin<T, A>>,
306 tx_d1: Peri<'d, impl TXD1Pin<T>>, 308 tx_d1: Peri<'d, impl TXD1Pin<T, A>>,
307 tx_d2: Peri<'d, impl TXD2Pin<T>>, 309 tx_d2: Peri<'d, impl TXD2Pin<T, A>>,
308 tx_d3: Peri<'d, impl TXD3Pin<T>>, 310 tx_d3: Peri<'d, impl TXD3Pin<T, A>>,
309 tx_en: Peri<'d, impl TXEnPin<T>>, 311 tx_en: Peri<'d, impl TXEnPin<T, A>>,
310 phy: P, 312 phy: P,
311 mac_addr: [u8; 6], 313 mac_addr: [u8; 6],
312 ) -> Self { 314 ) -> Self {
@@ -347,6 +349,8 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
347 { 349 {
348 config_in_pins!(rx_clk, tx_clk, rx_d0, rx_d1, rx_d2, rx_d3, rxdv); 350 config_in_pins!(rx_clk, tx_clk, rx_d0, rx_d1, rx_d2, rx_d3, rxdv);
349 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_d2, tx_d3, tx_en); 351 config_af_pins!(mdio, mdc, tx_d0, tx_d1, tx_d2, tx_d3, tx_en);
352 #[cfg(afio)]
353 rx_d0.afio_remap();
350 } 354 }
351 355
352 #[cfg(any(eth_v1b, eth_v1c))] 356 #[cfg(any(eth_v1b, eth_v1c))]
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 034c5dd88..96ad42c7f 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -65,19 +65,19 @@ macro_rules! config_pins {
65 65
66impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> { 66impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
67 /// Create a new RMII ethernet driver using 9 pins. 67 /// Create a new RMII ethernet driver using 9 pins.
68 pub fn new<const TX: usize, const RX: usize>( 68 pub fn new<const TX: usize, const RX: usize, A>(
69 queue: &'d mut PacketQueue<TX, RX>, 69 queue: &'d mut PacketQueue<TX, RX>,
70 peri: Peri<'d, T>, 70 peri: Peri<'d, T>,
71 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 71 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
72 ref_clk: Peri<'d, impl RefClkPin<T>>, 72 ref_clk: Peri<'d, impl RefClkPin<T, A>>,
73 mdio: Peri<'d, impl MDIOPin<T>>, 73 mdio: Peri<'d, impl MDIOPin<T, A>>,
74 mdc: Peri<'d, impl MDCPin<T>>, 74 mdc: Peri<'d, impl MDCPin<T, A>>,
75 crs: Peri<'d, impl CRSPin<T>>, 75 crs: Peri<'d, impl CRSPin<T, A>>,
76 rx_d0: Peri<'d, impl RXD0Pin<T>>, 76 rx_d0: Peri<'d, impl RXD0Pin<T, A>>,
77 rx_d1: Peri<'d, impl RXD1Pin<T>>, 77 rx_d1: Peri<'d, impl RXD1Pin<T, A>>,
78 tx_d0: Peri<'d, impl TXD0Pin<T>>, 78 tx_d0: Peri<'d, impl TXD0Pin<T, A>>,
79 tx_d1: Peri<'d, impl TXD1Pin<T>>, 79 tx_d1: Peri<'d, impl TXD1Pin<T, A>>,
80 tx_en: Peri<'d, impl TXEnPin<T>>, 80 tx_en: Peri<'d, impl TXEnPin<T, A>>,
81 phy: P, 81 phy: P,
82 mac_addr: [u8; 6], 82 mac_addr: [u8; 6],
83 ) -> Self { 83 ) -> Self {
@@ -110,24 +110,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
110 } 110 }
111 111
112 /// Create a new MII ethernet driver using 14 pins. 112 /// Create a new MII ethernet driver using 14 pins.
113 pub fn new_mii<const TX: usize, const RX: usize>( 113 pub fn new_mii<const TX: usize, const RX: usize, A>(
114 queue: &'d mut PacketQueue<TX, RX>, 114 queue: &'d mut PacketQueue<TX, RX>,
115 peri: Peri<'d, T>, 115 peri: Peri<'d, T>,
116 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd, 116 irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
117 rx_clk: Peri<'d, impl RXClkPin<T>>, 117 rx_clk: Peri<'d, impl RXClkPin<T, A>>,
118 tx_clk: Peri<'d, impl TXClkPin<T>>, 118 tx_clk: Peri<'d, impl TXClkPin<T, A>>,
119 mdio: Peri<'d, impl MDIOPin<T>>, 119 mdio: Peri<'d, impl MDIOPin<T, A>>,
120 mdc: Peri<'d, impl MDCPin<T>>, 120 mdc: Peri<'d, impl MDCPin<T, A>>,
121 rxdv: Peri<'d, impl RXDVPin<T>>, 121 rxdv: Peri<'d, impl RXDVPin<T, A>>,
122 rx_d0: Peri<'d, impl RXD0Pin<T>>, 122 rx_d0: Peri<'d, impl RXD0Pin<T, A>>,
123 rx_d1: Peri<'d, impl RXD1Pin<T>>, 123 rx_d1: Peri<'d, impl RXD1Pin<T, A>>,
124 rx_d2: Peri<'d, impl RXD2Pin<T>>, 124 rx_d2: Peri<'d, impl RXD2Pin<T, A>>,
125 rx_d3: Peri<'d, impl RXD3Pin<T>>, 125 rx_d3: Peri<'d, impl RXD3Pin<T, A>>,
126 tx_d0: Peri<'d, impl TXD0Pin<T>>, 126 tx_d0: Peri<'d, impl TXD0Pin<T, A>>,
127 tx_d1: Peri<'d, impl TXD1Pin<T>>, 127 tx_d1: Peri<'d, impl TXD1Pin<T, A>>,
128 tx_d2: Peri<'d, impl TXD2Pin<T>>, 128 tx_d2: Peri<'d, impl TXD2Pin<T, A>>,
129 tx_d3: Peri<'d, impl TXD3Pin<T>>, 129 tx_d3: Peri<'d, impl TXD3Pin<T, A>>,
130 tx_en: Peri<'d, impl TXEnPin<T>>, 130 tx_en: Peri<'d, impl TXEnPin<T, A>>,
131 phy: P, 131 phy: P,
132 mac_addr: [u8; 6], 132 mac_addr: [u8; 6],
133 ) -> Self { 133 ) -> Self {
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index bb37c4194..ef631bbdc 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -710,6 +710,17 @@ fn get_pull(pin_port: u8) -> Pull {
710 }; 710 };
711} 711}
712 712
713#[cfg(afio)]
714/// Holds the AFIO remap value for a peripheral's pin
715pub struct AfioRemap<const V: u8>;
716
717#[cfg(afio)]
718/// Holds the AFIO remap value for a peripheral's pin
719pub struct AfioRemapBool<const V: bool>;
720
721/// Placeholder for a peripheral's pin which cannot be remapped via AFIO.
722pub struct AfioRemapNotApplicable;
723
713pub(crate) trait SealedPin { 724pub(crate) trait SealedPin {
714 fn pin_port(&self) -> u8; 725 fn pin_port(&self) -> u8;
715 726
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 5fb49f943..be0ae2f5f 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -149,10 +149,10 @@ pub struct I2c<'d, M: Mode, IM: MasterMode> {
149 149
150impl<'d> I2c<'d, Async, Master> { 150impl<'d> I2c<'d, Async, Master> {
151 /// Create a new I2C driver. 151 /// Create a new I2C driver.
152 pub fn new<T: Instance>( 152 pub fn new<T: Instance, A>(
153 peri: Peri<'d, T>, 153 peri: Peri<'d, T>,
154 scl: Peri<'d, impl SclPin<T>>, 154 scl: Peri<'d, impl SclPin<T, A>>,
155 sda: Peri<'d, impl SdaPin<T>>, 155 sda: Peri<'d, impl SdaPin<T, A>>,
156 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> 156 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
157 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> 157 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
158 + 'd, 158 + 'd,
@@ -173,10 +173,10 @@ impl<'d> I2c<'d, Async, Master> {
173 173
174impl<'d> I2c<'d, Blocking, Master> { 174impl<'d> I2c<'d, Blocking, Master> {
175 /// Create a new blocking I2C driver. 175 /// Create a new blocking I2C driver.
176 pub fn new_blocking<T: Instance>( 176 pub fn new_blocking<T: Instance, A>(
177 peri: Peri<'d, T>, 177 peri: Peri<'d, T>,
178 scl: Peri<'d, impl SclPin<T>>, 178 scl: Peri<'d, impl SclPin<T, A>>,
179 sda: Peri<'d, impl SdaPin<T>>, 179 sda: Peri<'d, impl SdaPin<T, A>>,
180 config: Config, 180 config: Config,
181 ) -> Self { 181 ) -> Self {
182 Self::new_inner( 182 Self::new_inner(
@@ -296,8 +296,8 @@ peri_trait!(
296 irqs: [EventInterrupt, ErrorInterrupt], 296 irqs: [EventInterrupt, ErrorInterrupt],
297); 297);
298 298
299pin_trait!(SclPin, Instance); 299pin_trait!(SclPin, Instance, @A);
300pin_trait!(SdaPin, Instance); 300pin_trait!(SdaPin, Instance, @A);
301dma_trait!(RxDma, Instance); 301dma_trait!(RxDma, Instance);
302dma_trait!(TxDma, Instance); 302dma_trait!(TxDma, Instance);
303 303
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 0c4ab56e3..4c634aa17 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -237,12 +237,12 @@ pub struct I2S<'d, W: Word> {
237 237
238impl<'d, W: Word> I2S<'d, W> { 238impl<'d, W: Word> I2S<'d, W> {
239 /// Create a transmitter driver. 239 /// Create a transmitter driver.
240 pub fn new_txonly<T: Instance>( 240 pub fn new_txonly<T: Instance, A>(
241 peri: Peri<'d, T>, 241 peri: Peri<'d, T>,
242 sd: Peri<'d, impl MosiPin<T>>, 242 sd: Peri<'d, impl MosiPin<T, A>>,
243 ws: Peri<'d, impl WsPin<T>>, 243 ws: Peri<'d, impl WsPin<T, A>>,
244 ck: Peri<'d, impl CkPin<T>>, 244 ck: Peri<'d, impl CkPin<T, A>>,
245 mck: Peri<'d, impl MckPin<T>>, 245 mck: Peri<'d, impl MckPin<T, A>>,
246 txdma: Peri<'d, impl TxDma<T>>, 246 txdma: Peri<'d, impl TxDma<T>>,
247 txdma_buf: &'d mut [W], 247 txdma_buf: &'d mut [W],
248 config: Config, 248 config: Config,
@@ -262,11 +262,11 @@ impl<'d, W: Word> I2S<'d, W> {
262 } 262 }
263 263
264 /// Create a transmitter driver without a master clock pin. 264 /// Create a transmitter driver without a master clock pin.
265 pub fn new_txonly_nomck<T: Instance>( 265 pub fn new_txonly_nomck<T: Instance, A>(
266 peri: Peri<'d, T>, 266 peri: Peri<'d, T>,
267 sd: Peri<'d, impl MosiPin<T>>, 267 sd: Peri<'d, impl MosiPin<T, A>>,
268 ws: Peri<'d, impl WsPin<T>>, 268 ws: Peri<'d, impl WsPin<T, A>>,
269 ck: Peri<'d, impl CkPin<T>>, 269 ck: Peri<'d, impl CkPin<T, A>>,
270 txdma: Peri<'d, impl TxDma<T>>, 270 txdma: Peri<'d, impl TxDma<T>>,
271 txdma_buf: &'d mut [W], 271 txdma_buf: &'d mut [W],
272 config: Config, 272 config: Config,
@@ -286,12 +286,12 @@ impl<'d, W: Word> I2S<'d, W> {
286 } 286 }
287 287
288 /// Create a receiver driver. 288 /// Create a receiver driver.
289 pub fn new_rxonly<T: Instance>( 289 pub fn new_rxonly<T: Instance, A>(
290 peri: Peri<'d, T>, 290 peri: Peri<'d, T>,
291 sd: Peri<'d, impl MisoPin<T>>, 291 sd: Peri<'d, impl MisoPin<T, A>>,
292 ws: Peri<'d, impl WsPin<T>>, 292 ws: Peri<'d, impl WsPin<T, A>>,
293 ck: Peri<'d, impl CkPin<T>>, 293 ck: Peri<'d, impl CkPin<T, A>>,
294 mck: Peri<'d, impl MckPin<T>>, 294 mck: Peri<'d, impl MckPin<T, A>>,
295 rxdma: Peri<'d, impl RxDma<T>>, 295 rxdma: Peri<'d, impl RxDma<T>>,
296 rxdma_buf: &'d mut [W], 296 rxdma_buf: &'d mut [W],
297 config: Config, 297 config: Config,
@@ -313,13 +313,13 @@ impl<'d, W: Word> I2S<'d, W> {
313 #[cfg(any(spi_v4, spi_v5))] 313 #[cfg(any(spi_v4, spi_v5))]
314 314
315 /// Create a full duplex driver. 315 /// Create a full duplex driver.
316 pub fn new_full_duplex<T: Instance>( 316 pub fn new_full_duplex<T: Instance, A>(
317 peri: Peri<'d, T>, 317 peri: Peri<'d, T>,
318 txsd: Peri<'d, impl MosiPin<T>>, 318 txsd: Peri<'d, impl MosiPin<T, A>>,
319 rxsd: Peri<'d, impl MisoPin<T>>, 319 rxsd: Peri<'d, impl MisoPin<T, A>>,
320 ws: Peri<'d, impl WsPin<T>>, 320 ws: Peri<'d, impl WsPin<T, A>>,
321 ck: Peri<'d, impl CkPin<T>>, 321 ck: Peri<'d, impl CkPin<T, A>>,
322 mck: Peri<'d, impl MckPin<T>>, 322 mck: Peri<'d, impl MckPin<T, A>>,
323 txdma: Peri<'d, impl TxDma<T>>, 323 txdma: Peri<'d, impl TxDma<T>>,
324 txdma_buf: &'d mut [W], 324 txdma_buf: &'d mut [W],
325 rxdma: Peri<'d, impl RxDma<T>>, 325 rxdma: Peri<'d, impl RxDma<T>>,
@@ -459,12 +459,12 @@ impl<'d, W: Word> I2S<'d, W> {
459 } 459 }
460 } 460 }
461 461
462 fn new_inner<T: Instance>( 462 fn new_inner<T: Instance, A>(
463 peri: Peri<'d, T>, 463 peri: Peri<'d, T>,
464 txsd: Option<Peri<'d, AnyPin>>, 464 txsd: Option<Peri<'d, AnyPin>>,
465 rxsd: Option<Peri<'d, AnyPin>>, 465 rxsd: Option<Peri<'d, AnyPin>>,
466 ws: Peri<'d, impl WsPin<T>>, 466 ws: Peri<'d, impl WsPin<T, A>>,
467 ck: Peri<'d, impl CkPin<T>>, 467 ck: Peri<'d, impl CkPin<T, A>>,
468 mck: Option<Peri<'d, AnyPin>>, 468 mck: Option<Peri<'d, AnyPin>>,
469 txdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, 469 txdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>,
470 rxdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>, 470 rxdma: Option<(ChannelAndRequest<'d>, &'d mut [W])>,
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs
index 3a0b490ba..f97843a7d 100644
--- a/embassy-stm32/src/macros.rs
+++ b/embassy-stm32/src/macros.rs
@@ -41,25 +41,54 @@ macro_rules! peri_trait_impl {
41} 41}
42 42
43macro_rules! pin_trait { 43macro_rules! pin_trait {
44 ($signal:ident, $instance:path $(, $mode:path)?) => { 44 ($signal:ident, $instance:path $(, $mode:path)? $(, @$afio:ident)?) => {
45 #[doc = concat!(stringify!($signal), " pin trait")] 45 #[doc = concat!(stringify!($signal), " pin trait")]
46 pub trait $signal<T: $instance $(, M: $mode)?>: crate::gpio::Pin { 46 pub trait $signal<T: $instance $(, M: $mode)? $(, $afio)?>: crate::gpio::Pin {
47 #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] 47 #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))]
48 fn af_num(&self) -> u8; 48 fn af_num(&self) -> u8;
49
50 #[cfg(afio)]
51 #[doc = concat!("Configures AFIO_MAPR to use this pin as ", stringify!($signal))]
52 fn afio_remap(&self);
49 } 53 }
50 }; 54 };
51} 55}
52 56
53macro_rules! pin_trait_impl { 57macro_rules! pin_trait_impl {
54 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr) => { 58 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr $(, $afio:path)?) => {
55 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$pin { 59 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)? $(, $afio)?> for crate::peripherals::$pin {
56 fn af_num(&self) -> u8 { 60 fn af_num(&self) -> u8 {
57 $af 61 $af
58 } 62 }
63
64 #[cfg(afio)]
65 fn afio_remap(&self) {
66 // nothing
67 }
59 } 68 }
60 }; 69 };
61} 70}
62 71
72#[cfg(afio)]
73macro_rules! pin_trait_afio_impl {
74 (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$setter:ident, $type:ident, [$($val:expr),+]}) => {
75 $(
76 impl crate::$mod::$trait<crate::peripherals::$instance, crate::gpio::$type<$val>> for crate::peripherals::$pin {
77 fn af_num(&self) -> u8 {
78 0
79 }
80
81 fn afio_remap(&self) {
82 crate::pac::AFIO.mapr().modify(|w| {
83 w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP);
84 w.$setter($val);
85 });
86 }
87 }
88 )+
89 };
90}
91
63#[allow(unused_macros)] 92#[allow(unused_macros)]
64macro_rules! sel_trait_impl { 93macro_rules! sel_trait_impl {
65 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $sel:expr) => { 94 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $sel:expr) => {
@@ -73,6 +102,30 @@ macro_rules! sel_trait_impl {
73 102
74// ==================== 103// ====================
75 104
105macro_rules! timer_afio_impl {
106 ($instance:ident $(, $set_afio:expr)? $(,{$mapr_value:literal, [$($pin:literal),*]})*) => {
107 impl crate::timer::Afio for crate::peripherals::$instance {
108 fn afio_mappings() -> &'static [crate::timer::AfioMapping] {
109 &[
110 $(
111 crate::timer::AfioMapping {
112 value: $mapr_value,
113 pins: &[$($pin),*],
114 }
115 ),*
116 ]
117 }
118
119 #[allow(unused)]
120 fn set_afio(value: u8) {
121 $($set_afio(value);)?
122 }
123 }
124 };
125}
126
127// ====================
128
76macro_rules! dma_trait { 129macro_rules! dma_trait {
77 ($signal:ident, $instance:path$(, $mode:path)?) => { 130 ($signal:ident, $instance:path$(, $mode:path)?) => {
78 #[doc = concat!(stringify!($signal), " DMA request trait")] 131 #[doc = concat!(stringify!($signal), " DMA request trait")]
@@ -134,6 +187,8 @@ macro_rules! new_dma {
134macro_rules! new_pin { 187macro_rules! new_pin {
135 ($name:ident, $af_type:expr) => {{ 188 ($name:ident, $af_type:expr) => {{
136 let pin = $name; 189 let pin = $name;
190 #[cfg(afio)]
191 pin.afio_remap();
137 pin.set_as_af(pin.af_num(), $af_type); 192 pin.set_as_af(pin.af_num(), $af_type);
138 Some(pin.into()) 193 Some(pin.into())
139 }}; 194 }};
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index a49ebcbee..105c617d8 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -471,11 +471,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
471 471
472impl<'d> Spi<'d, Blocking> { 472impl<'d> Spi<'d, Blocking> {
473 /// Create a new blocking SPI driver. 473 /// Create a new blocking SPI driver.
474 pub fn new_blocking<T: Instance>( 474 pub fn new_blocking<T: Instance, A>(
475 peri: Peri<'d, T>, 475 peri: Peri<'d, T>,
476 sck: Peri<'d, impl SckPin<T>>, 476 sck: Peri<'d, impl SckPin<T, A>>,
477 mosi: Peri<'d, impl MosiPin<T>>, 477 mosi: Peri<'d, impl MosiPin<T, A>>,
478 miso: Peri<'d, impl MisoPin<T>>, 478 miso: Peri<'d, impl MisoPin<T, A>>,
479 config: Config, 479 config: Config,
480 ) -> Self { 480 ) -> Self {
481 Self::new_inner( 481 Self::new_inner(
@@ -490,10 +490,10 @@ impl<'d> Spi<'d, Blocking> {
490 } 490 }
491 491
492 /// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI). 492 /// Create a new blocking SPI driver, in RX-only mode (only MISO pin, no MOSI).
493 pub fn new_blocking_rxonly<T: Instance>( 493 pub fn new_blocking_rxonly<T: Instance, A>(
494 peri: Peri<'d, T>, 494 peri: Peri<'d, T>,
495 sck: Peri<'d, impl SckPin<T>>, 495 sck: Peri<'d, impl SckPin<T, A>>,
496 miso: Peri<'d, impl MisoPin<T>>, 496 miso: Peri<'d, impl MisoPin<T, A>>,
497 config: Config, 497 config: Config,
498 ) -> Self { 498 ) -> Self {
499 Self::new_inner( 499 Self::new_inner(
@@ -508,10 +508,10 @@ impl<'d> Spi<'d, Blocking> {
508 } 508 }
509 509
510 /// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO). 510 /// Create a new blocking SPI driver, in TX-only mode (only MOSI pin, no MISO).
511 pub fn new_blocking_txonly<T: Instance>( 511 pub fn new_blocking_txonly<T: Instance, A>(
512 peri: Peri<'d, T>, 512 peri: Peri<'d, T>,
513 sck: Peri<'d, impl SckPin<T>>, 513 sck: Peri<'d, impl SckPin<T, A>>,
514 mosi: Peri<'d, impl MosiPin<T>>, 514 mosi: Peri<'d, impl MosiPin<T, A>>,
515 config: Config, 515 config: Config,
516 ) -> Self { 516 ) -> Self {
517 Self::new_inner( 517 Self::new_inner(
@@ -528,9 +528,9 @@ impl<'d> Spi<'d, Blocking> {
528 /// Create a new SPI driver, in TX-only mode, without SCK pin. 528 /// Create a new SPI driver, in TX-only mode, without SCK pin.
529 /// 529 ///
530 /// This can be useful for bit-banging non-SPI protocols. 530 /// This can be useful for bit-banging non-SPI protocols.
531 pub fn new_blocking_txonly_nosck<T: Instance>( 531 pub fn new_blocking_txonly_nosck<T: Instance, A>(
532 peri: Peri<'d, T>, 532 peri: Peri<'d, T>,
533 mosi: Peri<'d, impl MosiPin<T>>, 533 mosi: Peri<'d, impl MosiPin<T, A>>,
534 config: Config, 534 config: Config,
535 ) -> Self { 535 ) -> Self {
536 Self::new_inner( 536 Self::new_inner(
@@ -547,11 +547,11 @@ impl<'d> Spi<'d, Blocking> {
547 547
548impl<'d> Spi<'d, Async> { 548impl<'d> Spi<'d, Async> {
549 /// Create a new SPI driver. 549 /// Create a new SPI driver.
550 pub fn new<T: Instance>( 550 pub fn new<T: Instance, A>(
551 peri: Peri<'d, T>, 551 peri: Peri<'d, T>,
552 sck: Peri<'d, impl SckPin<T>>, 552 sck: Peri<'d, impl SckPin<T, A>>,
553 mosi: Peri<'d, impl MosiPin<T>>, 553 mosi: Peri<'d, impl MosiPin<T, A>>,
554 miso: Peri<'d, impl MisoPin<T>>, 554 miso: Peri<'d, impl MisoPin<T, A>>,
555 tx_dma: Peri<'d, impl TxDma<T>>, 555 tx_dma: Peri<'d, impl TxDma<T>>,
556 rx_dma: Peri<'d, impl RxDma<T>>, 556 rx_dma: Peri<'d, impl RxDma<T>>,
557 config: Config, 557 config: Config,
@@ -568,10 +568,10 @@ impl<'d> Spi<'d, Async> {
568 } 568 }
569 569
570 /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI). 570 /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
571 pub fn new_rxonly<T: Instance>( 571 pub fn new_rxonly<T: Instance, A>(
572 peri: Peri<'d, T>, 572 peri: Peri<'d, T>,
573 sck: Peri<'d, impl SckPin<T>>, 573 sck: Peri<'d, impl SckPin<T, A>>,
574 miso: Peri<'d, impl MisoPin<T>>, 574 miso: Peri<'d, impl MisoPin<T, A>>,
575 #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma<T>>, 575 #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma<T>>,
576 rx_dma: Peri<'d, impl RxDma<T>>, 576 rx_dma: Peri<'d, impl RxDma<T>>,
577 config: Config, 577 config: Config,
@@ -591,10 +591,10 @@ impl<'d> Spi<'d, Async> {
591 } 591 }
592 592
593 /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO). 593 /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
594 pub fn new_txonly<T: Instance>( 594 pub fn new_txonly<T: Instance, A>(
595 peri: Peri<'d, T>, 595 peri: Peri<'d, T>,
596 sck: Peri<'d, impl SckPin<T>>, 596 sck: Peri<'d, impl SckPin<T, A>>,
597 mosi: Peri<'d, impl MosiPin<T>>, 597 mosi: Peri<'d, impl MosiPin<T, A>>,
598 tx_dma: Peri<'d, impl TxDma<T>>, 598 tx_dma: Peri<'d, impl TxDma<T>>,
599 config: Config, 599 config: Config,
600 ) -> Self { 600 ) -> Self {
@@ -612,9 +612,9 @@ impl<'d> Spi<'d, Async> {
612 /// Create a new SPI driver, in TX-only mode, without SCK pin. 612 /// Create a new SPI driver, in TX-only mode, without SCK pin.
613 /// 613 ///
614 /// This can be useful for bit-banging non-SPI protocols. 614 /// This can be useful for bit-banging non-SPI protocols.
615 pub fn new_txonly_nosck<T: Instance>( 615 pub fn new_txonly_nosck<T: Instance, A>(
616 peri: Peri<'d, T>, 616 peri: Peri<'d, T>,
617 mosi: Peri<'d, impl MosiPin<T>>, 617 mosi: Peri<'d, impl MosiPin<T, A>>,
618 tx_dma: Peri<'d, impl TxDma<T>>, 618 tx_dma: Peri<'d, impl TxDma<T>>,
619 config: Config, 619 config: Config,
620 ) -> Self { 620 ) -> Self {
@@ -1309,13 +1309,13 @@ impl State {
1309 1309
1310peri_trait!(); 1310peri_trait!();
1311 1311
1312pin_trait!(SckPin, Instance); 1312pin_trait!(SckPin, Instance, @A);
1313pin_trait!(MosiPin, Instance); 1313pin_trait!(MosiPin, Instance, @A);
1314pin_trait!(MisoPin, Instance); 1314pin_trait!(MisoPin, Instance, @A);
1315pin_trait!(CsPin, Instance); 1315pin_trait!(CsPin, Instance, @A);
1316pin_trait!(MckPin, Instance); 1316pin_trait!(MckPin, Instance, @A);
1317pin_trait!(CkPin, Instance); 1317pin_trait!(CkPin, Instance, @A);
1318pin_trait!(WsPin, Instance); 1318pin_trait!(WsPin, Instance, @A);
1319dma_trait!(RxDma, Instance); 1319dma_trait!(RxDma, Instance);
1320dma_trait!(TxDma, Instance); 1320dma_trait!(TxDma, Instance);
1321 1321
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 68cdec302..08404cdd6 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -17,7 +17,8 @@ use crate::Peri;
17/// 17///
18/// This wraps a pin to make it usable with PWM. 18/// This wraps a pin to make it usable with PWM.
19pub struct ComplementaryPwmPin<'d, T, C> { 19pub struct ComplementaryPwmPin<'d, T, C> {
20 _pin: Peri<'d, AnyPin>, 20 #[allow(unused)]
21 pin: Peri<'d, AnyPin>,
21 phantom: PhantomData<(T, C)>, 22 phantom: PhantomData<(T, C)>,
22} 23}
23 24
@@ -32,7 +33,7 @@ impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T
32 ); 33 );
33 }); 34 });
34 ComplementaryPwmPin { 35 ComplementaryPwmPin {
35 _pin: pin.into(), 36 pin: pin.into(),
36 phantom: PhantomData, 37 phantom: PhantomData,
37 } 38 }
38 } 39 }
@@ -54,20 +55,31 @@ pub enum IdlePolarity {
54 55
55impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { 56impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
56 /// Create a new complementary PWM driver. 57 /// Create a new complementary PWM driver.
57 #[allow(clippy::too_many_arguments)] 58 #[allow(clippy::too_many_arguments, unused)]
58 pub fn new( 59 pub fn new(
59 tim: Peri<'d, T>, 60 tim: Peri<'d, T>,
60 _ch1: Option<PwmPin<'d, T, Ch1>>, 61 ch1: Option<PwmPin<'d, T, Ch1>>,
61 _ch1n: Option<ComplementaryPwmPin<'d, T, Ch1>>, 62 ch1n: Option<ComplementaryPwmPin<'d, T, Ch1>>,
62 _ch2: Option<PwmPin<'d, T, Ch2>>, 63 ch2: Option<PwmPin<'d, T, Ch2>>,
63 _ch2n: Option<ComplementaryPwmPin<'d, T, Ch2>>, 64 ch2n: Option<ComplementaryPwmPin<'d, T, Ch2>>,
64 _ch3: Option<PwmPin<'d, T, Ch3>>, 65 ch3: Option<PwmPin<'d, T, Ch3>>,
65 _ch3n: Option<ComplementaryPwmPin<'d, T, Ch3>>, 66 ch3n: Option<ComplementaryPwmPin<'d, T, Ch3>>,
66 _ch4: Option<PwmPin<'d, T, Ch4>>, 67 ch4: Option<PwmPin<'d, T, Ch4>>,
67 _ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>, 68 ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>,
68 freq: Hertz, 69 freq: Hertz,
69 counting_mode: CountingMode, 70 counting_mode: CountingMode,
70 ) -> Self { 71 ) -> Self {
72 #[cfg(afio)]
73 super::set_afio::<T>(&[
74 ch1.map(|p| p.pin),
75 ch1n.map(|p| p.pin),
76 ch2.map(|p| p.pin),
77 ch2n.map(|p| p.pin),
78 ch3.map(|p| p.pin),
79 ch3n.map(|p| p.pin),
80 ch4.map(|p| p.pin),
81 ch4n.map(|p| p.pin),
82 ]);
71 Self::new_inner(tim, freq, counting_mode) 83 Self::new_inner(tim, freq, counting_mode)
72 } 84 }
73 85
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index dda33e7f1..b717e6eac 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -18,7 +18,8 @@ use crate::Peri;
18/// 18///
19/// This wraps a pin to make it usable with capture. 19/// This wraps a pin to make it usable with capture.
20pub struct CapturePin<'d, T, C> { 20pub struct CapturePin<'d, T, C> {
21 _pin: Peri<'d, AnyPin>, 21 #[allow(unused)]
22 pin: Peri<'d, AnyPin>,
22 phantom: PhantomData<(T, C)>, 23 phantom: PhantomData<(T, C)>,
23} 24}
24impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { 25impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
@@ -26,7 +27,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
26 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self { 27 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
27 pin.set_as_af(pin.af_num(), AfType::input(pull)); 28 pin.set_as_af(pin.af_num(), AfType::input(pull));
28 CapturePin { 29 CapturePin {
29 _pin: pin.into(), 30 pin: pin.into(),
30 phantom: PhantomData, 31 phantom: PhantomData,
31 } 32 }
32 } 33 }
@@ -39,16 +40,24 @@ pub struct InputCapture<'d, T: GeneralInstance4Channel> {
39 40
40impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { 41impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
41 /// Create a new input capture driver. 42 /// Create a new input capture driver.
43 #[allow(unused)]
42 pub fn new( 44 pub fn new(
43 tim: Peri<'d, T>, 45 tim: Peri<'d, T>,
44 _ch1: Option<CapturePin<'d, T, Ch1>>, 46 ch1: Option<CapturePin<'d, T, Ch1>>,
45 _ch2: Option<CapturePin<'d, T, Ch2>>, 47 ch2: Option<CapturePin<'d, T, Ch2>>,
46 _ch3: Option<CapturePin<'d, T, Ch3>>, 48 ch3: Option<CapturePin<'d, T, Ch3>>,
47 _ch4: Option<CapturePin<'d, T, Ch4>>, 49 ch4: Option<CapturePin<'d, T, Ch4>>,
48 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd, 50 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
49 freq: Hertz, 51 freq: Hertz,
50 counting_mode: CountingMode, 52 counting_mode: CountingMode,
51 ) -> Self { 53 ) -> Self {
54 #[cfg(afio)]
55 super::set_afio::<T>(&[
56 ch1.map(|p| p.pin),
57 ch2.map(|p| p.pin),
58 ch3.map(|p| p.pin),
59 ch4.map(|p| p.pin),
60 ]);
52 Self::new_inner(tim, freq, counting_mode) 61 Self::new_inner(tim, freq, counting_mode)
53 } 62 }
54 63
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 7062f5f4c..38f4a1a51 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -14,6 +14,8 @@ pub mod pwm_input;
14pub mod qei; 14pub mod qei;
15pub mod simple_pwm; 15pub mod simple_pwm;
16 16
17#[cfg(afio)]
18use crate::gpio::SealedPin;
17use crate::interrupt; 19use crate::interrupt;
18use crate::rcc::RccPeripheral; 20use crate::rcc::RccPeripheral;
19 21
@@ -155,9 +157,15 @@ trait SealedInstance: RccPeripheral + PeripheralType {
155 fn state() -> &'static State; 157 fn state() -> &'static State;
156} 158}
157 159
160#[allow(unused)]
161pub(crate) trait Afio {
162 fn afio_mappings() -> &'static [AfioMapping];
163 fn set_afio(value: u8);
164}
165
158/// Core timer instance. 166/// Core timer instance.
159#[allow(private_bounds)] 167#[allow(private_bounds)]
160pub trait CoreInstance: SealedInstance + 'static { 168pub trait CoreInstance: SealedInstance + Afio + 'static {
161 /// Update Interrupt for this timer. 169 /// Update Interrupt for this timer.
162 type UpdateInterrupt: interrupt::typelevel::Interrupt; 170 type UpdateInterrupt: interrupt::typelevel::Interrupt;
163 171
@@ -450,3 +458,24 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
450 } 458 }
451 } 459 }
452} 460}
461
462#[allow(unused)]
463pub(crate) struct AfioMapping {
464 pub(crate) value: u8,
465 pub(crate) pins: &'static [u8],
466}
467
468#[cfg(afio)]
469fn set_afio<'d, T: Afio>(pins: &[Option<embassy_hal_internal::Peri<'d, crate::gpio::AnyPin>>]) {
470 let mapping = T::afio_mappings()
471 .iter()
472 .find(|m| {
473 pins.iter()
474 .flatten()
475 .map(|p| (*p).pin_port())
476 .all(|p| m.pins.contains(&p))
477 })
478 .expect("Should be called with a combination of timer pins supported by the hardware");
479
480 T::set_afio(mapping.value);
481}
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index 498d9c082..0267749e1 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -42,7 +42,8 @@ impl From<ExternalTriggerPolarity> for Etp {
42/// 42///
43/// This wraps a pin to make it usable as a timer trigger. 43/// This wraps a pin to make it usable as a timer trigger.
44pub struct TriggerPin<'d, T, C> { 44pub struct TriggerPin<'d, T, C> {
45 _pin: Peri<'d, AnyPin>, 45 #[allow(unused)]
46 pin: Peri<'d, AnyPin>,
46 phantom: PhantomData<(T, C)>, 47 phantom: PhantomData<(T, C)>,
47} 48}
48 49
@@ -113,7 +114,7 @@ impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
113 pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self { 114 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 pin.set_as_af(pin.af_num(), AfType::input(pull));
115 TriggerPin { 116 TriggerPin {
116 _pin: pin.into(), 117 pin: pin.into(),
117 phantom: PhantomData, 118 phantom: PhantomData,
118 } 119 }
119 } 120 }
@@ -131,14 +132,17 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
131 /// 132 ///
132 /// The pulse is triggered by a channel 1 input pin on both rising and 133 /// The pulse is triggered by a channel 1 input pin on both rising and
133 /// falling edges. Channel 1 will unusable as an output. 134 /// falling edges. Channel 1 will unusable as an output.
135 #[allow(unused)]
134 pub fn new_ch1_edge_detect( 136 pub fn new_ch1_edge_detect(
135 tim: Peri<'d, T>, 137 tim: Peri<'d, T>,
136 _pin: TriggerPin<'d, T, Ch1>, 138 pin: TriggerPin<'d, T, Ch1>,
137 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd, 139 _irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
138 freq: Hertz, 140 freq: Hertz,
139 pulse_end: u32, 141 pulse_end: u32,
140 counting_mode: CountingMode, 142 counting_mode: CountingMode,
141 ) -> Self { 143 ) -> Self {
144 #[cfg(afio)]
145 super::set_afio::<T>(&[Some(pin.pin)]);
142 let mut this = Self { inner: Timer::new(tim) }; 146 let mut this = Self { inner: Timer::new(tim) };
143 147
144 this.inner.set_trigger_source(Ts::TI1F_ED); 148 this.inner.set_trigger_source(Ts::TI1F_ED);
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index 1e55f2919..c537e5268 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -20,6 +20,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
20 /// Create a new PWM input driver. 20 /// Create a new PWM input driver.
21 pub fn new_ch1(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, 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 {
22 pin.set_as_af(pin.af_num(), AfType::input(pull)); 22 pin.set_as_af(pin.af_num(), AfType::input(pull));
23 #[cfg(afio)]
24 super::set_afio::<T>(&[Some(pin.into())]);
23 25
24 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) 26 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
25 } 27 }
@@ -27,6 +29,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
27 /// Create a new PWM input driver. 29 /// Create a new PWM input driver.
28 pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self { 30 pub fn new_ch2(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
29 pin.set_as_af(pin.af_num(), AfType::input(pull)); 31 pin.set_as_af(pin.af_num(), AfType::input(pull));
32 #[cfg(afio)]
33 super::set_afio::<T>(&[Some(pin.into())]);
30 34
31 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) 35 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
32 } 36 }
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index eabe1b22a..4e5a309ac 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -21,19 +21,20 @@ pub enum Direction {
21 21
22/// Wrapper for using a pin with QEI. 22/// Wrapper for using a pin with QEI.
23pub struct QeiPin<'d, T, Channel> { 23pub struct QeiPin<'d, T, Channel> {
24 _pin: Peri<'d, AnyPin>, 24 #[allow(unused)]
25 pin: Peri<'d, AnyPin>,
25 phantom: PhantomData<(T, Channel)>, 26 phantom: PhantomData<(T, Channel)>,
26} 27}
27 28
28impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { 29impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
29 /// Create a new QEI pin instance. 30 /// Create a new QEI pin instance.
30 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self { 31 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
31 critical_section::with(|_| { 32 critical_section::with(|_| {
32 pin.set_low(); 33 pin.set_low();
33 pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); 34 pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
34 }); 35 });
35 QeiPin { 36 QeiPin {
36 _pin: pin.into(), 37 pin: pin.into(),
37 phantom: PhantomData, 38 phantom: PhantomData,
38 } 39 }
39 } 40 }
@@ -58,7 +59,10 @@ pub struct Qei<'d, T: GeneralInstance4Channel> {
58 59
59impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { 60impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
60 /// Create a new quadrature decoder driver. 61 /// Create a new quadrature decoder driver.
61 pub fn new(tim: Peri<'d, T>, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { 62 #[allow(unused)]
63 pub fn new(tim: Peri<'d, T>, ch1: QeiPin<'d, T, Ch1>, ch2: QeiPin<'d, T, Ch2>) -> Self {
64 #[cfg(afio)]
65 super::set_afio::<T>(&[Some(ch1.pin), Some(ch2.pin)]);
62 Self::new_inner(tim) 66 Self::new_inner(tim)
63 } 67 }
64 68
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index c04b1ab97..df86859fe 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -15,7 +15,8 @@ use crate::Peri;
15/// 15///
16/// This wraps a pin to make it usable with PWM. 16/// This wraps a pin to make it usable with PWM.
17pub struct PwmPin<'d, T, C> { 17pub struct PwmPin<'d, T, C> {
18 _pin: Peri<'d, AnyPin>, 18 #[allow(unused)]
19 pub(crate) pin: Peri<'d, AnyPin>,
19 phantom: PhantomData<(T, C)>, 20 phantom: PhantomData<(T, C)>,
20} 21}
21 22
@@ -42,7 +43,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
42 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); 43 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
43 }); 44 });
44 PwmPin { 45 PwmPin {
45 _pin: pin.into(), 46 pin: pin.into(),
46 phantom: PhantomData, 47 phantom: PhantomData,
47 } 48 }
48 } 49 }
@@ -60,7 +61,7 @@ impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
60 ); 61 );
61 }); 62 });
62 PwmPin { 63 PwmPin {
63 _pin: pin.into(), 64 pin: pin.into(),
64 phantom: PhantomData, 65 phantom: PhantomData,
65 } 66 }
66 } 67 }
@@ -178,15 +179,23 @@ pub struct SimplePwm<'d, T: GeneralInstance4Channel> {
178 179
179impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { 180impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
180 /// Create a new simple PWM driver. 181 /// Create a new simple PWM driver.
182 #[allow(unused)]
181 pub fn new( 183 pub fn new(
182 tim: Peri<'d, T>, 184 tim: Peri<'d, T>,
183 _ch1: Option<PwmPin<'d, T, Ch1>>, 185 ch1: Option<PwmPin<'d, T, Ch1>>,
184 _ch2: Option<PwmPin<'d, T, Ch2>>, 186 ch2: Option<PwmPin<'d, T, Ch2>>,
185 _ch3: Option<PwmPin<'d, T, Ch3>>, 187 ch3: Option<PwmPin<'d, T, Ch3>>,
186 _ch4: Option<PwmPin<'d, T, Ch4>>, 188 ch4: Option<PwmPin<'d, T, Ch4>>,
187 freq: Hertz, 189 freq: Hertz,
188 counting_mode: CountingMode, 190 counting_mode: CountingMode,
189 ) -> Self { 191 ) -> Self {
192 #[cfg(afio)]
193 super::set_afio::<T>(&[
194 ch1.map(|p| p.pin),
195 ch2.map(|p| p.pin),
196 ch3.map(|p| p.pin),
197 ch4.map(|p| p.pin),
198 ]);
190 Self::new_inner(tim, freq, counting_mode) 199 Self::new_inner(tim, freq, counting_mode)
191 } 200 }
192 201
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 729440c46..72aeb8357 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -208,10 +208,10 @@ impl<'d> SetConfig for BufferedUartTx<'d> {
208 208
209impl<'d> BufferedUart<'d> { 209impl<'d> BufferedUart<'d> {
210 /// Create a new bidirectional buffered UART driver 210 /// Create a new bidirectional buffered UART driver
211 pub fn new<T: Instance>( 211 pub fn new<T: Instance, A>(
212 peri: Peri<'d, T>, 212 peri: Peri<'d, T>,
213 rx: Peri<'d, impl RxPin<T>>, 213 rx: Peri<'d, impl RxPin<T, A>>,
214 tx: Peri<'d, impl TxPin<T>>, 214 tx: Peri<'d, impl TxPin<T, A>>,
215 tx_buffer: &'d mut [u8], 215 tx_buffer: &'d mut [u8],
216 rx_buffer: &'d mut [u8], 216 rx_buffer: &'d mut [u8],
217 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 217 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -231,12 +231,12 @@ impl<'d> BufferedUart<'d> {
231 } 231 }
232 232
233 /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins 233 /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
234 pub fn new_with_rtscts<T: Instance>( 234 pub fn new_with_rtscts<T: Instance, A>(
235 peri: Peri<'d, T>, 235 peri: Peri<'d, T>,
236 rx: Peri<'d, impl RxPin<T>>, 236 rx: Peri<'d, impl RxPin<T, A>>,
237 tx: Peri<'d, impl TxPin<T>>, 237 tx: Peri<'d, impl TxPin<T, A>>,
238 rts: Peri<'d, impl RtsPin<T>>, 238 rts: Peri<'d, impl RtsPin<T, A>>,
239 cts: Peri<'d, impl CtsPin<T>>, 239 cts: Peri<'d, impl CtsPin<T, A>>,
240 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 240 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
241 tx_buffer: &'d mut [u8], 241 tx_buffer: &'d mut [u8],
242 rx_buffer: &'d mut [u8], 242 rx_buffer: &'d mut [u8],
@@ -256,11 +256,11 @@ impl<'d> BufferedUart<'d> {
256 } 256 }
257 257
258 /// Create a new bidirectional buffered UART driver with only the RTS pin as the DE pin 258 /// Create a new bidirectional buffered UART driver with only the RTS pin as the DE pin
259 pub fn new_with_rts_as_de<T: Instance>( 259 pub fn new_with_rts_as_de<T: Instance, A>(
260 peri: Peri<'d, T>, 260 peri: Peri<'d, T>,
261 rx: Peri<'d, impl RxPin<T>>, 261 rx: Peri<'d, impl RxPin<T, A>>,
262 tx: Peri<'d, impl TxPin<T>>, 262 tx: Peri<'d, impl TxPin<T, A>>,
263 rts: Peri<'d, impl RtsPin<T>>, 263 rts: Peri<'d, impl RtsPin<T, A>>,
264 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 264 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
265 tx_buffer: &'d mut [u8], 265 tx_buffer: &'d mut [u8],
266 rx_buffer: &'d mut [u8], 266 rx_buffer: &'d mut [u8],
@@ -280,11 +280,11 @@ impl<'d> BufferedUart<'d> {
280 } 280 }
281 281
282 /// Create a new bidirectional buffered UART driver with only the request-to-send pin 282 /// Create a new bidirectional buffered UART driver with only the request-to-send pin
283 pub fn new_with_rts<T: Instance>( 283 pub fn new_with_rts<T: Instance, A>(
284 peri: Peri<'d, T>, 284 peri: Peri<'d, T>,
285 rx: Peri<'d, impl RxPin<T>>, 285 rx: Peri<'d, impl RxPin<T, A>>,
286 tx: Peri<'d, impl TxPin<T>>, 286 tx: Peri<'d, impl TxPin<T, A>>,
287 rts: Peri<'d, impl RtsPin<T>>, 287 rts: Peri<'d, impl RtsPin<T, A>>,
288 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 288 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
289 tx_buffer: &'d mut [u8], 289 tx_buffer: &'d mut [u8],
290 rx_buffer: &'d mut [u8], 290 rx_buffer: &'d mut [u8],
@@ -305,11 +305,11 @@ impl<'d> BufferedUart<'d> {
305 305
306 /// Create a new bidirectional buffered UART driver with a driver-enable pin 306 /// Create a new bidirectional buffered UART driver with a driver-enable pin
307 #[cfg(not(any(usart_v1, usart_v2)))] 307 #[cfg(not(any(usart_v1, usart_v2)))]
308 pub fn new_with_de<T: Instance>( 308 pub fn new_with_de<T: Instance, A>(
309 peri: Peri<'d, T>, 309 peri: Peri<'d, T>,
310 rx: Peri<'d, impl RxPin<T>>, 310 rx: Peri<'d, impl RxPin<T, A>>,
311 tx: Peri<'d, impl TxPin<T>>, 311 tx: Peri<'d, impl TxPin<T, A>>,
312 de: Peri<'d, impl DePin<T>>, 312 de: Peri<'d, impl DePin<T, A>>,
313 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 313 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
314 tx_buffer: &'d mut [u8], 314 tx_buffer: &'d mut [u8],
315 rx_buffer: &'d mut [u8], 315 rx_buffer: &'d mut [u8],
@@ -340,9 +340,9 @@ impl<'d> BufferedUart<'d> {
340 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict 340 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
341 /// on the line must be managed by software (for instance by using a centralized arbiter). 341 /// on the line must be managed by software (for instance by using a centralized arbiter).
342 #[doc(alias("HDSEL"))] 342 #[doc(alias("HDSEL"))]
343 pub fn new_half_duplex<T: Instance>( 343 pub fn new_half_duplex<T: Instance, A>(
344 peri: Peri<'d, T>, 344 peri: Peri<'d, T>,
345 tx: Peri<'d, impl TxPin<T>>, 345 tx: Peri<'d, impl TxPin<T, A>>,
346 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 346 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
347 tx_buffer: &'d mut [u8], 347 tx_buffer: &'d mut [u8],
348 rx_buffer: &'d mut [u8], 348 rx_buffer: &'d mut [u8],
@@ -379,9 +379,9 @@ impl<'d> BufferedUart<'d> {
379 /// on the line must be managed by software (for instance by using a centralized arbiter). 379 /// on the line must be managed by software (for instance by using a centralized arbiter).
380 #[cfg(not(any(usart_v1, usart_v2)))] 380 #[cfg(not(any(usart_v1, usart_v2)))]
381 #[doc(alias("HDSEL"))] 381 #[doc(alias("HDSEL"))]
382 pub fn new_half_duplex_on_rx<T: Instance>( 382 pub fn new_half_duplex_on_rx<T: Instance, A>(
383 peri: Peri<'d, T>, 383 peri: Peri<'d, T>,
384 rx: Peri<'d, impl RxPin<T>>, 384 rx: Peri<'d, impl RxPin<T, A>>,
385 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 385 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
386 tx_buffer: &'d mut [u8], 386 tx_buffer: &'d mut [u8],
387 rx_buffer: &'d mut [u8], 387 rx_buffer: &'d mut [u8],
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 3d95de897..21d174bf0 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -429,9 +429,9 @@ impl<'d, M: Mode> SetConfig for UartRx<'d, M> {
429 429
430impl<'d> UartTx<'d, Async> { 430impl<'d> UartTx<'d, Async> {
431 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. 431 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
432 pub fn new<T: Instance>( 432 pub fn new<T: Instance, A>(
433 peri: Peri<'d, T>, 433 peri: Peri<'d, T>,
434 tx: Peri<'d, impl TxPin<T>>, 434 tx: Peri<'d, impl TxPin<T, A>>,
435 tx_dma: Peri<'d, impl TxDma<T>>, 435 tx_dma: Peri<'d, impl TxDma<T>>,
436 config: Config, 436 config: Config,
437 ) -> Result<Self, ConfigError> { 437 ) -> Result<Self, ConfigError> {
@@ -439,10 +439,10 @@ impl<'d> UartTx<'d, Async> {
439 } 439 }
440 440
441 /// Create a new tx-only UART with a clear-to-send pin 441 /// Create a new tx-only UART with a clear-to-send pin
442 pub fn new_with_cts<T: Instance>( 442 pub fn new_with_cts<T: Instance, A>(
443 peri: Peri<'d, T>, 443 peri: Peri<'d, T>,
444 tx: Peri<'d, impl TxPin<T>>, 444 tx: Peri<'d, impl TxPin<T, A>>,
445 cts: Peri<'d, impl CtsPin<T>>, 445 cts: Peri<'d, impl CtsPin<T, A>>,
446 tx_dma: Peri<'d, impl TxDma<T>>, 446 tx_dma: Peri<'d, impl TxDma<T>>,
447 config: Config, 447 config: Config,
448 ) -> Result<Self, ConfigError> { 448 ) -> Result<Self, ConfigError> {
@@ -482,19 +482,19 @@ impl<'d> UartTx<'d, Blocking> {
482 /// Create a new blocking tx-only UART with no hardware flow control. 482 /// Create a new blocking tx-only UART with no hardware flow control.
483 /// 483 ///
484 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. 484 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
485 pub fn new_blocking<T: Instance>( 485 pub fn new_blocking<T: Instance, A>(
486 peri: Peri<'d, T>, 486 peri: Peri<'d, T>,
487 tx: Peri<'d, impl TxPin<T>>, 487 tx: Peri<'d, impl TxPin<T, A>>,
488 config: Config, 488 config: Config,
489 ) -> Result<Self, ConfigError> { 489 ) -> Result<Self, ConfigError> {
490 Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, None, config) 490 Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, None, config)
491 } 491 }
492 492
493 /// Create a new blocking tx-only UART with a clear-to-send pin 493 /// Create a new blocking tx-only UART with a clear-to-send pin
494 pub fn new_blocking_with_cts<T: Instance>( 494 pub fn new_blocking_with_cts<T: Instance, A>(
495 peri: Peri<'d, T>, 495 peri: Peri<'d, T>,
496 tx: Peri<'d, impl TxPin<T>>, 496 tx: Peri<'d, impl TxPin<T, A>>,
497 cts: Peri<'d, impl CtsPin<T>>, 497 cts: Peri<'d, impl CtsPin<T, A>>,
498 config: Config, 498 config: Config,
499 ) -> Result<Self, ConfigError> { 499 ) -> Result<Self, ConfigError> {
500 Self::new_inner( 500 Self::new_inner(
@@ -662,10 +662,10 @@ impl<'d> UartRx<'d, Async> {
662 /// Create a new rx-only UART with no hardware flow control. 662 /// Create a new rx-only UART with no hardware flow control.
663 /// 663 ///
664 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. 664 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
665 pub fn new<T: Instance>( 665 pub fn new<T: Instance, A>(
666 peri: Peri<'d, T>, 666 peri: Peri<'d, T>,
667 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 667 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
668 rx: Peri<'d, impl RxPin<T>>, 668 rx: Peri<'d, impl RxPin<T, A>>,
669 rx_dma: Peri<'d, impl RxDma<T>>, 669 rx_dma: Peri<'d, impl RxDma<T>>,
670 config: Config, 670 config: Config,
671 ) -> Result<Self, ConfigError> { 671 ) -> Result<Self, ConfigError> {
@@ -673,11 +673,11 @@ impl<'d> UartRx<'d, Async> {
673 } 673 }
674 674
675 /// Create a new rx-only UART with a request-to-send pin 675 /// Create a new rx-only UART with a request-to-send pin
676 pub fn new_with_rts<T: Instance>( 676 pub fn new_with_rts<T: Instance, A>(
677 peri: Peri<'d, T>, 677 peri: Peri<'d, T>,
678 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 678 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
679 rx: Peri<'d, impl RxPin<T>>, 679 rx: Peri<'d, impl RxPin<T, A>>,
680 rts: Peri<'d, impl RtsPin<T>>, 680 rts: Peri<'d, impl RtsPin<T, A>>,
681 rx_dma: Peri<'d, impl RxDma<T>>, 681 rx_dma: Peri<'d, impl RxDma<T>>,
682 config: Config, 682 config: Config,
683 ) -> Result<Self, ConfigError> { 683 ) -> Result<Self, ConfigError> {
@@ -913,19 +913,19 @@ impl<'d> UartRx<'d, Blocking> {
913 /// Create a new rx-only UART with no hardware flow control. 913 /// Create a new rx-only UART with no hardware flow control.
914 /// 914 ///
915 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. 915 /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
916 pub fn new_blocking<T: Instance>( 916 pub fn new_blocking<T: Instance, A>(
917 peri: Peri<'d, T>, 917 peri: Peri<'d, T>,
918 rx: Peri<'d, impl RxPin<T>>, 918 rx: Peri<'d, impl RxPin<T, A>>,
919 config: Config, 919 config: Config,
920 ) -> Result<Self, ConfigError> { 920 ) -> Result<Self, ConfigError> {
921 Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, None, config) 921 Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, None, config)
922 } 922 }
923 923
924 /// Create a new rx-only UART with a request-to-send pin 924 /// Create a new rx-only UART with a request-to-send pin
925 pub fn new_blocking_with_rts<T: Instance>( 925 pub fn new_blocking_with_rts<T: Instance, A>(
926 peri: Peri<'d, T>, 926 peri: Peri<'d, T>,
927 rx: Peri<'d, impl RxPin<T>>, 927 rx: Peri<'d, impl RxPin<T, A>>,
928 rts: Peri<'d, impl RtsPin<T>>, 928 rts: Peri<'d, impl RtsPin<T, A>>,
929 config: Config, 929 config: Config,
930 ) -> Result<Self, ConfigError> { 930 ) -> Result<Self, ConfigError> {
931 Self::new_inner( 931 Self::new_inner(
@@ -1109,10 +1109,10 @@ fn drop_tx_rx(info: &Info, state: &State) {
1109 1109
1110impl<'d> Uart<'d, Async> { 1110impl<'d> Uart<'d, Async> {
1111 /// Create a new bidirectional UART 1111 /// Create a new bidirectional UART
1112 pub fn new<T: Instance>( 1112 pub fn new<T: Instance, A>(
1113 peri: Peri<'d, T>, 1113 peri: Peri<'d, T>,
1114 rx: Peri<'d, impl RxPin<T>>, 1114 rx: Peri<'d, impl RxPin<T, A>>,
1115 tx: Peri<'d, impl TxPin<T>>, 1115 tx: Peri<'d, impl TxPin<T, A>>,
1116 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 1116 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1117 tx_dma: Peri<'d, impl TxDma<T>>, 1117 tx_dma: Peri<'d, impl TxDma<T>>,
1118 rx_dma: Peri<'d, impl RxDma<T>>, 1118 rx_dma: Peri<'d, impl RxDma<T>>,
@@ -1132,13 +1132,13 @@ impl<'d> Uart<'d, Async> {
1132 } 1132 }
1133 1133
1134 /// Create a new bidirectional UART with request-to-send and clear-to-send pins 1134 /// Create a new bidirectional UART with request-to-send and clear-to-send pins
1135 pub fn new_with_rtscts<T: Instance>( 1135 pub fn new_with_rtscts<T: Instance, A>(
1136 peri: Peri<'d, T>, 1136 peri: Peri<'d, T>,
1137 rx: Peri<'d, impl RxPin<T>>, 1137 rx: Peri<'d, impl RxPin<T, A>>,
1138 tx: Peri<'d, impl TxPin<T>>, 1138 tx: Peri<'d, impl TxPin<T, A>>,
1139 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 1139 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1140 rts: Peri<'d, impl RtsPin<T>>, 1140 rts: Peri<'d, impl RtsPin<T, A>>,
1141 cts: Peri<'d, impl CtsPin<T>>, 1141 cts: Peri<'d, impl CtsPin<T, A>>,
1142 tx_dma: Peri<'d, impl TxDma<T>>, 1142 tx_dma: Peri<'d, impl TxDma<T>>,
1143 rx_dma: Peri<'d, impl RxDma<T>>, 1143 rx_dma: Peri<'d, impl RxDma<T>>,
1144 config: Config, 1144 config: Config,
@@ -1158,12 +1158,12 @@ impl<'d> Uart<'d, Async> {
1158 1158
1159 #[cfg(not(any(usart_v1, usart_v2)))] 1159 #[cfg(not(any(usart_v1, usart_v2)))]
1160 /// Create a new bidirectional UART with a driver-enable pin 1160 /// Create a new bidirectional UART with a driver-enable pin
1161 pub fn new_with_de<T: Instance>( 1161 pub fn new_with_de<T: Instance, A>(
1162 peri: Peri<'d, T>, 1162 peri: Peri<'d, T>,
1163 rx: Peri<'d, impl RxPin<T>>, 1163 rx: Peri<'d, impl RxPin<T, A>>,
1164 tx: Peri<'d, impl TxPin<T>>, 1164 tx: Peri<'d, impl TxPin<T, A>>,
1165 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 1165 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1166 de: Peri<'d, impl DePin<T>>, 1166 de: Peri<'d, impl DePin<T, A>>,
1167 tx_dma: Peri<'d, impl TxDma<T>>, 1167 tx_dma: Peri<'d, impl TxDma<T>>,
1168 rx_dma: Peri<'d, impl RxDma<T>>, 1168 rx_dma: Peri<'d, impl RxDma<T>>,
1169 config: Config, 1169 config: Config,
@@ -1193,9 +1193,9 @@ impl<'d> Uart<'d, Async> {
1193 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict 1193 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
1194 /// on the line must be managed by software (for instance by using a centralized arbiter). 1194 /// on the line must be managed by software (for instance by using a centralized arbiter).
1195 #[doc(alias("HDSEL"))] 1195 #[doc(alias("HDSEL"))]
1196 pub fn new_half_duplex<T: Instance>( 1196 pub fn new_half_duplex<T: Instance, A>(
1197 peri: Peri<'d, T>, 1197 peri: Peri<'d, T>,
1198 tx: Peri<'d, impl TxPin<T>>, 1198 tx: Peri<'d, impl TxPin<T, A>>,
1199 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 1199 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1200 tx_dma: Peri<'d, impl TxDma<T>>, 1200 tx_dma: Peri<'d, impl TxDma<T>>,
1201 rx_dma: Peri<'d, impl RxDma<T>>, 1201 rx_dma: Peri<'d, impl RxDma<T>>,
@@ -1232,9 +1232,9 @@ impl<'d> Uart<'d, Async> {
1232 /// on the line must be managed by software (for instance by using a centralized arbiter). 1232 /// on the line must be managed by software (for instance by using a centralized arbiter).
1233 #[cfg(not(any(usart_v1, usart_v2)))] 1233 #[cfg(not(any(usart_v1, usart_v2)))]
1234 #[doc(alias("HDSEL"))] 1234 #[doc(alias("HDSEL"))]
1235 pub fn new_half_duplex_on_rx<T: Instance>( 1235 pub fn new_half_duplex_on_rx<T: Instance, A>(
1236 peri: Peri<'d, T>, 1236 peri: Peri<'d, T>,
1237 rx: Peri<'d, impl RxPin<T>>, 1237 rx: Peri<'d, impl RxPin<T, A>>,
1238 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 1238 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1239 tx_dma: Peri<'d, impl TxDma<T>>, 1239 tx_dma: Peri<'d, impl TxDma<T>>,
1240 rx_dma: Peri<'d, impl RxDma<T>>, 1240 rx_dma: Peri<'d, impl RxDma<T>>,
@@ -1280,10 +1280,10 @@ impl<'d> Uart<'d, Async> {
1280 1280
1281impl<'d> Uart<'d, Blocking> { 1281impl<'d> Uart<'d, Blocking> {
1282 /// Create a new blocking bidirectional UART. 1282 /// Create a new blocking bidirectional UART.
1283 pub fn new_blocking<T: Instance>( 1283 pub fn new_blocking<T: Instance, A>(
1284 peri: Peri<'d, T>, 1284 peri: Peri<'d, T>,
1285 rx: Peri<'d, impl RxPin<T>>, 1285 rx: Peri<'d, impl RxPin<T, A>>,
1286 tx: Peri<'d, impl TxPin<T>>, 1286 tx: Peri<'d, impl TxPin<T, A>>,
1287 config: Config, 1287 config: Config,
1288 ) -> Result<Self, ConfigError> { 1288 ) -> Result<Self, ConfigError> {
1289 Self::new_inner( 1289 Self::new_inner(
@@ -1300,12 +1300,12 @@ impl<'d> Uart<'d, Blocking> {
1300 } 1300 }
1301 1301
1302 /// Create a new bidirectional UART with request-to-send and clear-to-send pins 1302 /// Create a new bidirectional UART with request-to-send and clear-to-send pins
1303 pub fn new_blocking_with_rtscts<T: Instance>( 1303 pub fn new_blocking_with_rtscts<T: Instance, A>(
1304 peri: Peri<'d, T>, 1304 peri: Peri<'d, T>,
1305 rx: Peri<'d, impl RxPin<T>>, 1305 rx: Peri<'d, impl RxPin<T, A>>,
1306 tx: Peri<'d, impl TxPin<T>>, 1306 tx: Peri<'d, impl TxPin<T, A>>,
1307 rts: Peri<'d, impl RtsPin<T>>, 1307 rts: Peri<'d, impl RtsPin<T, A>>,
1308 cts: Peri<'d, impl CtsPin<T>>, 1308 cts: Peri<'d, impl CtsPin<T, A>>,
1309 config: Config, 1309 config: Config,
1310 ) -> Result<Self, ConfigError> { 1310 ) -> Result<Self, ConfigError> {
1311 Self::new_inner( 1311 Self::new_inner(
@@ -1323,11 +1323,11 @@ impl<'d> Uart<'d, Blocking> {
1323 1323
1324 #[cfg(not(any(usart_v1, usart_v2)))] 1324 #[cfg(not(any(usart_v1, usart_v2)))]
1325 /// Create a new bidirectional UART with a driver-enable pin 1325 /// Create a new bidirectional UART with a driver-enable pin
1326 pub fn new_blocking_with_de<T: Instance>( 1326 pub fn new_blocking_with_de<T: Instance, A>(
1327 peri: Peri<'d, T>, 1327 peri: Peri<'d, T>,
1328 rx: Peri<'d, impl RxPin<T>>, 1328 rx: Peri<'d, impl RxPin<T, A>>,
1329 tx: Peri<'d, impl TxPin<T>>, 1329 tx: Peri<'d, impl TxPin<T, A>>,
1330 de: Peri<'d, impl DePin<T>>, 1330 de: Peri<'d, impl DePin<T, A>>,
1331 config: Config, 1331 config: Config,
1332 ) -> Result<Self, ConfigError> { 1332 ) -> Result<Self, ConfigError> {
1333 Self::new_inner( 1333 Self::new_inner(
@@ -1354,9 +1354,9 @@ impl<'d> Uart<'d, Blocking> {
1354 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict 1354 /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
1355 /// on the line must be managed by software (for instance by using a centralized arbiter). 1355 /// on the line must be managed by software (for instance by using a centralized arbiter).
1356 #[doc(alias("HDSEL"))] 1356 #[doc(alias("HDSEL"))]
1357 pub fn new_blocking_half_duplex<T: Instance>( 1357 pub fn new_blocking_half_duplex<T: Instance, A>(
1358 peri: Peri<'d, T>, 1358 peri: Peri<'d, T>,
1359 tx: Peri<'d, impl TxPin<T>>, 1359 tx: Peri<'d, impl TxPin<T, A>>,
1360 mut config: Config, 1360 mut config: Config,
1361 readback: HalfDuplexReadback, 1361 readback: HalfDuplexReadback,
1362 ) -> Result<Self, ConfigError> { 1362 ) -> Result<Self, ConfigError> {
@@ -1390,9 +1390,9 @@ impl<'d> Uart<'d, Blocking> {
1390 /// on the line must be managed by software (for instance by using a centralized arbiter). 1390 /// on the line must be managed by software (for instance by using a centralized arbiter).
1391 #[cfg(not(any(usart_v1, usart_v2)))] 1391 #[cfg(not(any(usart_v1, usart_v2)))]
1392 #[doc(alias("HDSEL"))] 1392 #[doc(alias("HDSEL"))]
1393 pub fn new_blocking_half_duplex_on_rx<T: Instance>( 1393 pub fn new_blocking_half_duplex_on_rx<T: Instance, A>(
1394 peri: Peri<'d, T>, 1394 peri: Peri<'d, T>,
1395 rx: Peri<'d, impl RxPin<T>>, 1395 rx: Peri<'d, impl RxPin<T, A>>,
1396 mut config: Config, 1396 mut config: Config,
1397 readback: HalfDuplexReadback, 1397 readback: HalfDuplexReadback,
1398 ) -> Result<Self, ConfigError> { 1398 ) -> Result<Self, ConfigError> {
@@ -2055,12 +2055,12 @@ pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
2055 type Interrupt: interrupt::typelevel::Interrupt; 2055 type Interrupt: interrupt::typelevel::Interrupt;
2056} 2056}
2057 2057
2058pin_trait!(RxPin, Instance); 2058pin_trait!(RxPin, Instance, @A);
2059pin_trait!(TxPin, Instance); 2059pin_trait!(TxPin, Instance, @A);
2060pin_trait!(CtsPin, Instance); 2060pin_trait!(CtsPin, Instance, @A);
2061pin_trait!(RtsPin, Instance); 2061pin_trait!(RtsPin, Instance, @A);
2062pin_trait!(CkPin, Instance); 2062pin_trait!(CkPin, Instance, @A);
2063pin_trait!(DePin, Instance); 2063pin_trait!(DePin, Instance, @A);
2064 2064
2065dma_trait!(TxDma, Instance); 2065dma_trait!(TxDma, Instance);
2066dma_trait!(RxDma, Instance); 2066dma_trait!(RxDma, Instance);
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index aeca67659..891ec93fd 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -9,7 +9,9 @@ publish = false
9[features] 9[features]
10stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"] 10stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"]
11stm32c071rb = ["embassy-stm32/stm32c071rb", "cm0", "not-gpdma"] 11stm32c071rb = ["embassy-stm32/stm32c071rb", "cm0", "not-gpdma"]
12stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma"] 12stm32f100rd = ["embassy-stm32/stm32f100rd", "spi-v1", "not-gpdma", "afio", "afio-value-line"]
13stm32f103c8 = ["embassy-stm32/stm32f103c8", "spi-v1", "not-gpdma", "afio"]
14stm32f107vc = ["embassy-stm32/stm32f107vc", "spi-v1", "not-gpdma", "afio", "afio-connectivity-line"]
13stm32f207zg = ["embassy-stm32/stm32f207zg", "spi-v1", "chrono", "not-gpdma", "eth", "rng"] 15stm32f207zg = ["embassy-stm32/stm32f207zg", "spi-v1", "chrono", "not-gpdma", "eth", "rng"]
14stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] 16stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"]
15stm32f429zi = ["embassy-stm32/stm32f429zi", "spi-v1", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"] 17stm32f429zi = ["embassy-stm32/stm32f429zi", "spi-v1", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"]
@@ -59,6 +61,9 @@ cordic = ["dep:num-traits"]
59dual-bank = ["embassy-stm32/dual-bank"] 61dual-bank = ["embassy-stm32/dual-bank"]
60single-bank = ["embassy-stm32/single-bank"] 62single-bank = ["embassy-stm32/single-bank"]
61eeprom = [] 63eeprom = []
64afio = []
65afio-connectivity-line = []
66afio-value-line = []
62 67
63cm0 = ["portable-atomic/unsafe-assume-single-core"] 68cm0 = ["portable-atomic/unsafe-assume-single-core"]
64 69
@@ -99,6 +104,11 @@ num-traits = { version="0.2", default-features = false,features = ["libm"], opti
99# BEGIN TESTS 104# BEGIN TESTS
100# Generated by gen_test.py. DO NOT EDIT. 105# Generated by gen_test.py. DO NOT EDIT.
101[[bin]] 106[[bin]]
107name = "afio"
108path = "src/bin/afio.rs"
109required-features = [ "afio",]
110
111[[bin]]
102name = "can" 112name = "can"
103path = "src/bin/can.rs" 113path = "src/bin/can.rs"
104required-features = [ "can",] 114required-features = [ "can",]
diff --git a/tests/stm32/src/bin/afio.rs b/tests/stm32/src/bin/afio.rs
new file mode 100644
index 000000000..c684b7b3e
--- /dev/null
+++ b/tests/stm32/src/bin/afio.rs
@@ -0,0 +1,1156 @@
1// required-features: afio
2#![no_std]
3#![no_main]
4#[path = "../common.rs"]
5mod common;
6
7use common::*;
8use embassy_executor::Spawner;
9use embassy_stm32::gpio::{OutputType, Pull};
10use embassy_stm32::pac::AFIO;
11use embassy_stm32::time::khz;
12use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
13use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
14use embassy_stm32::timer::pwm_input::PwmInput;
15use embassy_stm32::timer::qei::{Qei, QeiPin};
16use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
17use embassy_stm32::usart::{Uart, UartRx, UartTx};
18use embassy_stm32::{bind_interrupts, Peripherals};
19
20#[cfg(not(feature = "afio-connectivity-line"))]
21bind_interrupts!(struct Irqs {
22 USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;
23 TIM1_CC => embassy_stm32::timer::CaptureCompareInterruptHandler<embassy_stm32::peripherals::TIM1>;
24});
25
26#[cfg(feature = "afio-connectivity-line")]
27bind_interrupts!(struct Irqs {
28 CAN1_RX0 => embassy_stm32::can::Rx0InterruptHandler<embassy_stm32::peripherals::CAN1>;
29 CAN1_RX1 => embassy_stm32::can::Rx1InterruptHandler<embassy_stm32::peripherals::CAN1>;
30 CAN1_SCE => embassy_stm32::can::SceInterruptHandler<embassy_stm32::peripherals::CAN1>;
31 CAN1_TX => embassy_stm32::can::TxInterruptHandler<embassy_stm32::peripherals::CAN1>;
32
33 CAN2_RX0 => embassy_stm32::can::Rx0InterruptHandler<embassy_stm32::peripherals::CAN2>;
34 CAN2_RX1 => embassy_stm32::can::Rx1InterruptHandler<embassy_stm32::peripherals::CAN2>;
35 CAN2_SCE => embassy_stm32::can::SceInterruptHandler<embassy_stm32::peripherals::CAN2>;
36 CAN2_TX => embassy_stm32::can::TxInterruptHandler<embassy_stm32::peripherals::CAN2>;
37
38 ETH => embassy_stm32::eth::InterruptHandler;
39 USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;
40 TIM1_CC => embassy_stm32::timer::CaptureCompareInterruptHandler<embassy_stm32::peripherals::TIM1>;
41});
42
43#[embassy_executor::main]
44async fn main(_spawner: Spawner) {
45 let mut p = init();
46 info!("Hello World!");
47
48 // USART3
49 {
50 // no remap RX/TX/RTS/CTS
51 afio_registers_set_remap();
52 Uart::new_blocking_with_rtscts(
53 p.USART3.reborrow(),
54 p.PB11.reborrow(),
55 p.PB10.reborrow(),
56 p.PB14.reborrow(),
57 p.PB13.reborrow(),
58 Default::default(),
59 )
60 .unwrap();
61 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
62 }
63 {
64 // no remap RX/TX
65 afio_registers_set_remap();
66 Uart::new_blocking(
67 p.USART3.reborrow(),
68 p.PB11.reborrow(),
69 p.PB10.reborrow(),
70 Default::default(),
71 )
72 .unwrap();
73 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
74 }
75 {
76 // no remap TX
77 afio_registers_set_remap();
78 Uart::new_blocking_half_duplex(
79 p.USART3.reborrow(),
80 p.PB10.reborrow(),
81 Default::default(),
82 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
83 )
84 .unwrap();
85 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
86 }
87 {
88 // no remap TX async
89 afio_registers_set_remap();
90 UartTx::new(
91 p.USART3.reborrow(),
92 p.PB10.reborrow(),
93 p.DMA1_CH2.reborrow(),
94 Default::default(),
95 )
96 .unwrap();
97 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
98 }
99 {
100 // no remap TX/CTS async
101 afio_registers_set_remap();
102 UartTx::new_with_cts(
103 p.USART3.reborrow(),
104 p.PB10.reborrow(),
105 p.PB13.reborrow(),
106 p.DMA1_CH2.reborrow(),
107 Default::default(),
108 )
109 .unwrap();
110 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
111 }
112 {
113 // no remap RX async
114 afio_registers_set_remap();
115 UartRx::new(
116 p.USART3.reborrow(),
117 Irqs,
118 p.PB11.reborrow(),
119 p.DMA1_CH3.reborrow(),
120 Default::default(),
121 )
122 .unwrap();
123 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
124 }
125 {
126 // no remap RX async
127 afio_registers_set_remap();
128 UartRx::new_with_rts(
129 p.USART3.reborrow(),
130 Irqs,
131 p.PB11.reborrow(),
132 p.PB14.reborrow(),
133 p.DMA1_CH3.reborrow(),
134 Default::default(),
135 )
136 .unwrap();
137 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
138 }
139 {
140 // no remap RX/TX async
141 afio_registers_set_remap();
142 Uart::new(
143 p.USART3.reborrow(),
144 p.PB11.reborrow(),
145 p.PB10.reborrow(),
146 Irqs,
147 p.DMA1_CH2.reborrow(),
148 p.DMA1_CH3.reborrow(),
149 Default::default(),
150 )
151 .unwrap();
152 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
153 }
154 {
155 // no remap RX/TX/RTS/CTS async
156 afio_registers_set_remap();
157 Uart::new_with_rtscts(
158 p.USART3.reborrow(),
159 p.PB11.reborrow(),
160 p.PB10.reborrow(),
161 Irqs,
162 p.PB14.reborrow(),
163 p.PB13.reborrow(),
164 p.DMA1_CH2.reborrow(),
165 p.DMA1_CH3.reborrow(),
166 Default::default(),
167 )
168 .unwrap();
169 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 0);
170 }
171
172 // TIM1
173 {
174 // no remap
175 afio_registers_set_remap();
176 SimplePwm::new(
177 p.TIM1.reborrow(),
178 Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
179 Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)),
180 Some(PwmPin::new(p.PA10.reborrow(), OutputType::PushPull)),
181 Some(PwmPin::new(p.PA11.reborrow(), OutputType::PushPull)),
182 khz(10),
183 Default::default(),
184 );
185 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 0);
186 }
187 {
188 // no remap
189 afio_registers_set_remap();
190 SimplePwm::new(
191 p.TIM1.reborrow(),
192 Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
193 None,
194 None,
195 None,
196 khz(10),
197 Default::default(),
198 );
199 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 0);
200 }
201 {
202 // partial remap
203 reset_afio_registers();
204 ComplementaryPwm::new(
205 p.TIM1.reborrow(),
206 Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
207 None,
208 None,
209 None,
210 None,
211 None,
212 None,
213 None,
214 khz(10),
215 Default::default(),
216 );
217 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
218 }
219 {
220 // partial remap
221 reset_afio_registers();
222 ComplementaryPwm::new(
223 p.TIM1.reborrow(),
224 Some(PwmPin::new(p.PA8.reborrow(), OutputType::PushPull)),
225 Some(ComplementaryPwmPin::new(p.PA7.reborrow(), OutputType::PushPull)),
226 Some(PwmPin::new(p.PA9.reborrow(), OutputType::PushPull)),
227 Some(ComplementaryPwmPin::new(p.PB0.reborrow(), OutputType::PushPull)),
228 Some(PwmPin::new(p.PA10.reborrow(), OutputType::PushPull)),
229 None, // pin does not exist on medium-density devices
230 Some(PwmPin::new(p.PA11.reborrow(), OutputType::PushPull)),
231 None, // signal does not exist
232 khz(10),
233 Default::default(),
234 );
235 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
236 }
237 {
238 // partial remap
239 reset_afio_registers();
240 InputCapture::new(
241 p.TIM1.reborrow(),
242 Some(CapturePin::new(p.PA8.reborrow(), Pull::Down)),
243 None,
244 None,
245 None,
246 Irqs,
247 khz(10),
248 Default::default(),
249 );
250 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
251 }
252 {
253 // partial remap
254 reset_afio_registers();
255 PwmInput::new_ch1(p.TIM1.reborrow(), p.PA8.reborrow(), Pull::Down, khz(10));
256 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
257 }
258 {
259 // partial remap
260 reset_afio_registers();
261 Qei::new(
262 p.TIM1.reborrow(),
263 QeiPin::new(p.PA8.reborrow()),
264 QeiPin::new(p.PA9.reborrow()),
265 );
266 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 1);
267 }
268
269 // TIM2
270 {
271 // no remap
272 afio_registers_set_remap();
273 SimplePwm::new(
274 p.TIM2.reborrow(),
275 Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)),
276 Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)),
277 Some(PwmPin::new(p.PA2.reborrow(), OutputType::PushPull)),
278 Some(PwmPin::new(p.PA3.reborrow(), OutputType::PushPull)),
279 khz(10),
280 Default::default(),
281 );
282 defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 0);
283 }
284 {
285 // partial remap 1
286 reset_afio_registers();
287 SimplePwm::new(
288 p.TIM2.reborrow(),
289 Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)),
290 Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)),
291 Some(PwmPin::new(p.PA2.reborrow(), OutputType::PushPull)),
292 Some(PwmPin::new(p.PA3.reborrow(), OutputType::PushPull)),
293 khz(10),
294 Default::default(),
295 );
296 defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 1);
297 }
298 {
299 // partial remap 2
300 reset_afio_registers();
301 SimplePwm::new(
302 p.TIM2.reborrow(),
303 Some(PwmPin::new(p.PA0.reborrow(), OutputType::PushPull)),
304 Some(PwmPin::new(p.PA1.reborrow(), OutputType::PushPull)),
305 Some(PwmPin::new(p.PB10.reborrow(), OutputType::PushPull)),
306 Some(PwmPin::new(p.PB11.reborrow(), OutputType::PushPull)),
307 khz(10),
308 Default::default(),
309 );
310 defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 2);
311 }
312 {
313 // full remap
314 reset_afio_registers();
315 SimplePwm::new(
316 p.TIM2.reborrow(),
317 Some(PwmPin::new(p.PA15.reborrow(), OutputType::PushPull)),
318 Some(PwmPin::new(p.PB3.reborrow(), OutputType::PushPull)),
319 Some(PwmPin::new(p.PB10.reborrow(), OutputType::PushPull)),
320 Some(PwmPin::new(p.PB11.reborrow(), OutputType::PushPull)),
321 khz(10),
322 Default::default(),
323 );
324 defmt::assert_eq!(AFIO.mapr().read().tim2_remap(), 3);
325 }
326
327 connectivity_line::run(&mut p);
328 value_line::run(&mut p);
329
330 info!("Test OK");
331 cortex_m::asm::bkpt();
332}
333
334#[cfg(feature = "afio-connectivity-line")]
335mod connectivity_line {
336 use embassy_stm32::can::Can;
337 use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue};
338 use embassy_stm32::i2s::I2S;
339 use embassy_stm32::spi::Spi;
340
341 use super::*;
342
343 pub fn run(p: &mut Peripherals) {
344 // USART3
345 {
346 // partial remap RX/TX/RTS/CTS
347 reset_afio_registers();
348 Uart::new_blocking_with_rtscts(
349 p.USART3.reborrow(),
350 p.PC11.reborrow(),
351 p.PC10.reborrow(),
352 p.PB14.reborrow(),
353 p.PB13.reborrow(),
354 Default::default(),
355 )
356 .unwrap();
357 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
358 }
359 {
360 // partial remap RX/TX
361 reset_afio_registers();
362 Uart::new_blocking(
363 p.USART3.reborrow(),
364 p.PC11.reborrow(),
365 p.PC10.reborrow(),
366 Default::default(),
367 )
368 .unwrap();
369 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
370 }
371 {
372 // partial remap TX
373 reset_afio_registers();
374 Uart::new_blocking_half_duplex(
375 p.USART3.reborrow(),
376 p.PC10.reborrow(),
377 Default::default(),
378 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
379 )
380 .unwrap();
381 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
382 }
383 {
384 // partial remap TX async
385 reset_afio_registers();
386 UartTx::new(
387 p.USART3.reborrow(),
388 p.PC10.reborrow(),
389 p.DMA1_CH2.reborrow(),
390 Default::default(),
391 )
392 .unwrap();
393 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
394 }
395 {
396 // partial remap TX/CTS async
397 reset_afio_registers();
398 UartTx::new_with_cts(
399 p.USART3.reborrow(),
400 p.PC10.reborrow(),
401 p.PB13.reborrow(),
402 p.DMA1_CH2.reborrow(),
403 Default::default(),
404 )
405 .unwrap();
406 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
407 }
408 {
409 // partial remap RX async
410 reset_afio_registers();
411 UartRx::new(
412 p.USART3.reborrow(),
413 Irqs,
414 p.PC11.reborrow(),
415 p.DMA1_CH3.reborrow(),
416 Default::default(),
417 )
418 .unwrap();
419 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
420 }
421 {
422 // partial remap RX async
423 reset_afio_registers();
424 UartRx::new_with_rts(
425 p.USART3.reborrow(),
426 Irqs,
427 p.PC11.reborrow(),
428 p.PB14.reborrow(),
429 p.DMA1_CH3.reborrow(),
430 Default::default(),
431 )
432 .unwrap();
433 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
434 }
435 {
436 // partial remap RX/TX async
437 reset_afio_registers();
438 Uart::new(
439 p.USART3.reborrow(),
440 p.PC11.reborrow(),
441 p.PC10.reborrow(),
442 Irqs,
443 p.DMA1_CH2.reborrow(),
444 p.DMA1_CH3.reborrow(),
445 Default::default(),
446 )
447 .unwrap();
448 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
449 }
450 {
451 // partial remap RX/TX/RTS/CTS async
452 reset_afio_registers();
453 Uart::new_with_rtscts(
454 p.USART3.reborrow(),
455 p.PC11.reborrow(),
456 p.PC10.reborrow(),
457 Irqs,
458 p.PB14.reborrow(),
459 p.PB13.reborrow(),
460 p.DMA1_CH2.reborrow(),
461 p.DMA1_CH3.reborrow(),
462 Default::default(),
463 )
464 .unwrap();
465 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 1);
466 }
467 {
468 // full remap RX/TX/RTS/CTS
469 reset_afio_registers();
470 Uart::new_blocking_with_rtscts(
471 p.USART3.reborrow(),
472 p.PD9.reborrow(),
473 p.PD8.reborrow(),
474 p.PD12.reborrow(),
475 p.PD11.reborrow(),
476 Default::default(),
477 )
478 .unwrap();
479 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
480 }
481 {
482 // full remap RX/TX
483 reset_afio_registers();
484 Uart::new_blocking(
485 p.USART3.reborrow(),
486 p.PD9.reborrow(),
487 p.PD8.reborrow(),
488 Default::default(),
489 )
490 .unwrap();
491 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
492 }
493 {
494 // full remap TX
495 reset_afio_registers();
496 Uart::new_blocking_half_duplex(
497 p.USART3.reborrow(),
498 p.PD8.reborrow(),
499 Default::default(),
500 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
501 )
502 .unwrap();
503 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
504 }
505 {
506 // full remap TX async
507 reset_afio_registers();
508 UartTx::new(
509 p.USART3.reborrow(),
510 p.PD8.reborrow(),
511 p.DMA1_CH2.reborrow(),
512 Default::default(),
513 )
514 .unwrap();
515 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
516 }
517 {
518 // full remap TX/CTS async
519 reset_afio_registers();
520 UartTx::new_with_cts(
521 p.USART3.reborrow(),
522 p.PD8.reborrow(),
523 p.PD11.reborrow(),
524 p.DMA1_CH2.reborrow(),
525 Default::default(),
526 )
527 .unwrap();
528 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
529 }
530 {
531 // full remap RX async
532 reset_afio_registers();
533 UartRx::new(
534 p.USART3.reborrow(),
535 Irqs,
536 p.PD9.reborrow(),
537 p.DMA1_CH3.reborrow(),
538 Default::default(),
539 )
540 .unwrap();
541 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
542 }
543 {
544 // full remap RX async
545 reset_afio_registers();
546 UartRx::new_with_rts(
547 p.USART3.reborrow(),
548 Irqs,
549 p.PD9.reborrow(),
550 p.PD12.reborrow(),
551 p.DMA1_CH3.reborrow(),
552 Default::default(),
553 )
554 .unwrap();
555 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
556 }
557 {
558 // full remap RX/TX async
559 reset_afio_registers();
560 Uart::new(
561 p.USART3.reborrow(),
562 p.PD9.reborrow(),
563 p.PD8.reborrow(),
564 Irqs,
565 p.DMA1_CH2.reborrow(),
566 p.DMA1_CH3.reborrow(),
567 Default::default(),
568 )
569 .unwrap();
570 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
571 }
572 {
573 // full remap RX/TX/RTS/CTS async
574 reset_afio_registers();
575 Uart::new_with_rtscts(
576 p.USART3.reborrow(),
577 p.PD9.reborrow(),
578 p.PD8.reborrow(),
579 Irqs,
580 p.PD12.reborrow(),
581 p.PD11.reborrow(),
582 p.DMA1_CH2.reborrow(),
583 p.DMA1_CH3.reborrow(),
584 Default::default(),
585 )
586 .unwrap();
587 defmt::assert_eq!(AFIO.mapr().read().usart3_remap(), 3);
588 }
589
590 // SPI3
591 {
592 // no remap SCK/MISO/MOSI
593 afio_registers_set_remap();
594 Spi::new_blocking(
595 p.SPI3.reborrow(),
596 p.PB3.reborrow(),
597 p.PB5.reborrow(),
598 p.PB4.reborrow(),
599 Default::default(),
600 );
601 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
602 }
603 {
604 // no remap SCK/MOSI
605 afio_registers_set_remap();
606 Spi::new_blocking_txonly(
607 p.SPI3.reborrow(),
608 p.PB3.reborrow(),
609 p.PB5.reborrow(),
610 Default::default(),
611 );
612 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
613 }
614 {
615 // no remap MOSI
616 afio_registers_set_remap();
617 Spi::new_blocking_txonly_nosck(p.SPI3.reborrow(), p.PB5.reborrow(), Default::default());
618 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
619 }
620 {
621 // no remap SCK/MISO
622 afio_registers_set_remap();
623 Spi::new_blocking_rxonly(
624 p.SPI3.reborrow(),
625 p.PB3.reborrow(),
626 p.PB4.reborrow(),
627 Default::default(),
628 );
629 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
630 }
631 {
632 // remap SCK/MISO/MOSI
633 reset_afio_registers();
634 Spi::new_blocking(
635 p.SPI3.reborrow(),
636 p.PC10.reborrow(),
637 p.PC12.reborrow(),
638 p.PC11.reborrow(),
639 Default::default(),
640 );
641
642 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
643 }
644 {
645 // remap SCK/MOSI
646 reset_afio_registers();
647 Spi::new_blocking_txonly(
648 p.SPI3.reborrow(),
649 p.PC10.reborrow(),
650 p.PC12.reborrow(),
651 Default::default(),
652 );
653 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
654 }
655 {
656 // remap MOSI
657 reset_afio_registers();
658 Spi::new_blocking_txonly_nosck(p.SPI3.reborrow(), p.PB5.reborrow(), Default::default());
659 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
660 }
661 {
662 // remap SCK/MISO
663 reset_afio_registers();
664 Spi::new_blocking_rxonly(
665 p.SPI3.reborrow(),
666 p.PC10.reborrow(),
667 p.PC11.reborrow(),
668 Default::default(),
669 );
670 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
671 }
672
673 // I2S3
674 {
675 // no remap SD/WS/CK/MCK
676 afio_registers_set_remap();
677 I2S::new_txonly(
678 p.SPI3.reborrow(),
679 p.PB5.reborrow(),
680 p.PA15.reborrow(),
681 p.PB3.reborrow(),
682 p.PC7.reborrow(),
683 p.DMA2_CH2.reborrow(),
684 &mut [0u16; 0],
685 Default::default(),
686 );
687 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
688 }
689 {
690 // no remap SD/WS/CK
691 afio_registers_set_remap();
692 I2S::new_txonly_nomck(
693 p.SPI3.reborrow(),
694 p.PB5.reborrow(),
695 p.PA15.reborrow(),
696 p.PB3.reborrow(),
697 p.DMA2_CH2.reborrow(),
698 &mut [0u16; 0],
699 Default::default(),
700 );
701 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), false);
702 }
703 {
704 // no remap SD/WS/CK/MCK
705 afio_registers_set_remap();
706 I2S::new_rxonly(
707 p.SPI3.reborrow(),
708 p.PB4.reborrow(),
709 p.PA15.reborrow(),
710 p.PB3.reborrow(),
711 p.PC7.reborrow(),
712 p.DMA2_CH1.reborrow(),
713 &mut [0u16; 0],
714 Default::default(),
715 );
716 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
717 }
718 {
719 // remap SD/WS/CK/MCK
720 reset_afio_registers();
721 I2S::new_txonly(
722 p.SPI3.reborrow(),
723 p.PC12.reborrow(),
724 p.PA4.reborrow(),
725 p.PC10.reborrow(),
726 p.PC7.reborrow(),
727 p.DMA2_CH2.reborrow(),
728 &mut [0u16; 0],
729 Default::default(),
730 );
731 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
732 }
733 {
734 // remap SD/WS/CK
735 reset_afio_registers();
736 I2S::new_txonly_nomck(
737 p.SPI3.reborrow(),
738 p.PC12.reborrow(),
739 p.PA4.reborrow(),
740 p.PC10.reborrow(),
741 p.DMA2_CH2.reborrow(),
742 &mut [0u16; 0],
743 Default::default(),
744 );
745 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
746 }
747 {
748 // remap SD/WS/CK/MCK
749 reset_afio_registers();
750 I2S::new_rxonly(
751 p.SPI3.reborrow(),
752 p.PC11.reborrow(),
753 p.PA4.reborrow(),
754 p.PC10.reborrow(),
755 p.PC7.reborrow(),
756 p.DMA2_CH1.reborrow(),
757 &mut [0u16; 0],
758 Default::default(),
759 );
760 defmt::assert_eq!(AFIO.mapr().read().spi3_remap(), true);
761 }
762
763 // CAN2
764 {
765 // no remap
766 afio_registers_set_remap();
767 Can::new(p.CAN2.reborrow(), p.PB12.reborrow(), p.PB13.reborrow(), Irqs);
768 defmt::assert_eq!(AFIO.mapr().read().can2_remap(), false);
769 }
770 {
771 // remap
772 reset_afio_registers();
773 Can::new(p.CAN2.reborrow(), p.PB5.reborrow(), p.PB6.reborrow(), Irqs);
774 defmt::assert_eq!(AFIO.mapr().read().can2_remap(), true);
775 }
776
777 // Ethernet
778 {
779 // no remap RMII
780 afio_registers_set_remap();
781 Ethernet::new(
782 &mut PacketQueue::<1, 1>::new(),
783 p.ETH.reborrow(),
784 Irqs,
785 p.PA1.reborrow(),
786 p.PA2.reborrow(),
787 p.PC1.reborrow(),
788 p.PA7.reborrow(),
789 p.PC4.reborrow(),
790 p.PC5.reborrow(),
791 p.PB12.reborrow(),
792 p.PB13.reborrow(),
793 p.PB11.reborrow(),
794 GenericPhy::new_auto(),
795 Default::default(),
796 );
797 defmt::assert_eq!(AFIO.mapr().read().eth_remap(), false);
798 }
799 {
800 // no remap MII
801 afio_registers_set_remap();
802 Ethernet::new_mii(
803 &mut PacketQueue::<1, 1>::new(),
804 p.ETH.reborrow(),
805 Irqs,
806 p.PA1.reborrow(),
807 p.PC3.reborrow(),
808 p.PA2.reborrow(),
809 p.PC1.reborrow(),
810 p.PA7.reborrow(),
811 p.PC4.reborrow(),
812 p.PC5.reborrow(),
813 p.PB0.reborrow(),
814 p.PB1.reborrow(),
815 p.PB12.reborrow(),
816 p.PB13.reborrow(),
817 p.PC2.reborrow(),
818 p.PB8.reborrow(),
819 p.PB11.reborrow(),
820 GenericPhy::new_auto(),
821 Default::default(),
822 );
823 defmt::assert_eq!(AFIO.mapr().read().eth_remap(), false);
824 }
825 {
826 // remap RMII
827 reset_afio_registers();
828 Ethernet::new(
829 &mut PacketQueue::<1, 1>::new(),
830 p.ETH.reborrow(),
831 Irqs,
832 p.PA1.reborrow(),
833 p.PA2.reborrow(),
834 p.PC1.reborrow(),
835 p.PD8.reborrow(),
836 p.PD9.reborrow(),
837 p.PD10.reborrow(),
838 p.PB12.reborrow(),
839 p.PB13.reborrow(),
840 p.PB11.reborrow(),
841 GenericPhy::new_auto(),
842 Default::default(),
843 );
844 defmt::assert_eq!(AFIO.mapr().read().eth_remap(), true);
845 }
846 {
847 // remap MII
848 reset_afio_registers();
849 Ethernet::new_mii(
850 &mut PacketQueue::<1, 1>::new(),
851 p.ETH.reborrow(),
852 Irqs,
853 p.PA1.reborrow(),
854 p.PC3.reborrow(),
855 p.PA2.reborrow(),
856 p.PC1.reborrow(),
857 p.PD8.reborrow(),
858 p.PD9.reborrow(),
859 p.PD10.reborrow(),
860 p.PD11.reborrow(),
861 p.PD12.reborrow(),
862 p.PB12.reborrow(),
863 p.PB13.reborrow(),
864 p.PC2.reborrow(),
865 p.PB8.reborrow(),
866 p.PB11.reborrow(),
867 GenericPhy::new_auto(),
868 Default::default(),
869 );
870 defmt::assert_eq!(AFIO.mapr().read().eth_remap(), true);
871 }
872
873 // CAN1
874 {
875 // no remap
876 afio_registers_set_remap();
877 Can::new(p.CAN1.reborrow(), p.PA11.reborrow(), p.PA12.reborrow(), Irqs);
878 defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 0);
879 }
880 {
881 // partial remap
882 reset_afio_registers();
883 Can::new(p.CAN1.reborrow(), p.PB8.reborrow(), p.PB9.reborrow(), Irqs);
884 defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 2);
885 }
886 {
887 // full remap
888 reset_afio_registers();
889 Can::new(p.CAN1.reborrow(), p.PD0.reborrow(), p.PD1.reborrow(), Irqs);
890 defmt::assert_eq!(AFIO.mapr().read().can1_remap(), 3);
891 }
892
893 // USART2
894 {
895 // no remap RX/TX/RTS/CTS
896 afio_registers_set_remap();
897 Uart::new_blocking_with_rtscts(
898 p.USART2.reborrow(),
899 p.PA3.reborrow(),
900 p.PA2.reborrow(),
901 p.PA1.reborrow(),
902 p.PA0.reborrow(),
903 Default::default(),
904 )
905 .unwrap();
906 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false);
907 }
908 {
909 // no remap RX/TX
910 afio_registers_set_remap();
911 Uart::new_blocking(
912 p.USART2.reborrow(),
913 p.PA3.reborrow(),
914 p.PA2.reborrow(),
915 Default::default(),
916 )
917 .unwrap();
918 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false);
919 }
920 {
921 // no remap TX
922 afio_registers_set_remap();
923 Uart::new_blocking_half_duplex(
924 p.USART2.reborrow(),
925 p.PA2.reborrow(),
926 Default::default(),
927 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
928 )
929 .unwrap();
930 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false);
931 }
932 {
933 // full remap RX/TX/RTS/CTS
934 reset_afio_registers();
935 Uart::new_blocking_with_rtscts(
936 p.USART2.reborrow(),
937 p.PD6.reborrow(),
938 p.PD5.reborrow(),
939 p.PD4.reborrow(),
940 p.PD3.reborrow(),
941 Default::default(),
942 )
943 .unwrap();
944 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false);
945 }
946 {
947 // full remap RX/TX
948 reset_afio_registers();
949 Uart::new_blocking(
950 p.USART2.reborrow(),
951 p.PD6.reborrow(),
952 p.PD5.reborrow(),
953 Default::default(),
954 )
955 .unwrap();
956 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), false);
957 }
958 {
959 // full remap TX
960 reset_afio_registers();
961 Uart::new_blocking_half_duplex(
962 p.USART2.reborrow(),
963 p.PD5.reborrow(),
964 Default::default(),
965 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
966 )
967 .unwrap();
968 defmt::assert_eq!(AFIO.mapr().read().usart2_remap(), true);
969 }
970
971 // USART1
972 {
973 // no remap RX/TX/RTS/CTS
974 afio_registers_set_remap();
975 Uart::new_blocking_with_rtscts(
976 p.USART1.reborrow(),
977 p.PA10.reborrow(),
978 p.PA9.reborrow(),
979 p.PA12.reborrow(),
980 p.PA11.reborrow(),
981 Default::default(),
982 )
983 .unwrap();
984 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false);
985 }
986 {
987 // no remap RX/TX
988 afio_registers_set_remap();
989 Uart::new_blocking(
990 p.USART1.reborrow(),
991 p.PA10.reborrow(),
992 p.PA9.reborrow(),
993 Default::default(),
994 )
995 .unwrap();
996 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false);
997 }
998 {
999 // no remap TX
1000 afio_registers_set_remap();
1001 Uart::new_blocking_half_duplex(
1002 p.USART1.reborrow(),
1003 p.PA9.reborrow(),
1004 Default::default(),
1005 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
1006 )
1007 .unwrap();
1008 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), false);
1009 }
1010 {
1011 // remap RX/TX/RTS/CTS
1012 reset_afio_registers();
1013 Uart::new_blocking_with_rtscts(
1014 p.USART1.reborrow(),
1015 p.PB7.reborrow(),
1016 p.PB6.reborrow(),
1017 p.PA12.reborrow(),
1018 p.PA11.reborrow(),
1019 Default::default(),
1020 )
1021 .unwrap();
1022 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true);
1023 }
1024 {
1025 // remap RX/TX
1026 reset_afio_registers();
1027 Uart::new_blocking(
1028 p.USART1.reborrow(),
1029 p.PB7.reborrow(),
1030 p.PB6.reborrow(),
1031 Default::default(),
1032 )
1033 .unwrap();
1034 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true);
1035 }
1036 {
1037 // remap TX
1038 reset_afio_registers();
1039 Uart::new_blocking_half_duplex(
1040 p.USART1.reborrow(),
1041 p.PB6.reborrow(),
1042 Default::default(),
1043 embassy_stm32::usart::HalfDuplexReadback::NoReadback,
1044 )
1045 .unwrap();
1046 defmt::assert_eq!(AFIO.mapr().read().usart1_remap(), true);
1047 }
1048
1049 // TIM1
1050 {
1051 // full remap
1052 reset_afio_registers();
1053 SimplePwm::new(
1054 p.TIM1.reborrow(),
1055 Some(PwmPin::new(p.PE9.reborrow(), OutputType::PushPull)),
1056 Some(PwmPin::new(p.PE11.reborrow(), OutputType::PushPull)),
1057 None,
1058 None,
1059 khz(10),
1060 Default::default(),
1061 );
1062 defmt::assert_eq!(AFIO.mapr().read().tim1_remap(), 3);
1063 }
1064 }
1065}
1066
1067#[cfg(feature = "afio-value-line")]
1068mod value_line {
1069 use super::*;
1070
1071 pub fn run(p: &mut Peripherals) {
1072 // TIM13
1073 {
1074 // no remap
1075 reset_afio_registers();
1076 SimplePwm::new(
1077 p.TIM13.reborrow(),
1078 Some(PwmPin::new(p.PC8.reborrow(), OutputType::PushPull)),
1079 None,
1080 None,
1081 None,
1082 khz(10),
1083 Default::default(),
1084 );
1085 defmt::assert_eq!(AFIO.mapr2().read().tim13_remap(), false);
1086 }
1087 {
1088 // remap
1089 reset_afio_registers();
1090 SimplePwm::new(
1091 p.TIM13.reborrow(),
1092 Some(PwmPin::new(p.PB0.reborrow(), OutputType::PushPull)),
1093 None,
1094 None,
1095 None,
1096 khz(10),
1097 Default::default(),
1098 );
1099 defmt::assert_eq!(AFIO.mapr2().read().tim13_remap(), true);
1100 }
1101 }
1102}
1103
1104#[cfg(not(feature = "afio-connectivity-line"))]
1105mod connectivity_line {
1106 use super::*;
1107
1108 pub fn run(_: &mut Peripherals) {}
1109}
1110
1111#[cfg(not(feature = "afio-value-line"))]
1112mod value_line {
1113 use super::*;
1114
1115 pub fn run(_: &mut Peripherals) {}
1116}
1117
1118fn reset_afio_registers() {
1119 set_afio_registers(false, 0);
1120}
1121
1122fn afio_registers_set_remap() {
1123 set_afio_registers(true, 1);
1124}
1125
1126fn set_afio_registers(bool_val: bool, num_val: u8) {
1127 AFIO.mapr().modify(|w| {
1128 w.set_swj_cfg(embassy_stm32::pac::afio::vals::SwjCfg::NO_OP);
1129 w.set_can1_remap(num_val);
1130 w.set_can2_remap(bool_val);
1131 w.set_eth_remap(bool_val);
1132 w.set_i2c1_remap(bool_val);
1133 w.set_spi1_remap(bool_val);
1134 w.set_spi3_remap(bool_val);
1135 w.set_tim1_remap(num_val);
1136 w.set_tim2_remap(num_val);
1137 w.set_tim3_remap(num_val);
1138 w.set_tim4_remap(bool_val);
1139 w.set_usart1_remap(bool_val);
1140 w.set_usart2_remap(bool_val);
1141 w.set_usart3_remap(num_val);
1142 });
1143
1144 AFIO.mapr2().modify(|w| {
1145 w.set_cec_remap(bool_val);
1146 w.set_tim9_remap(bool_val);
1147 w.set_tim10_remap(bool_val);
1148 w.set_tim11_remap(bool_val);
1149 w.set_tim12_remap(bool_val);
1150 w.set_tim13_remap(bool_val);
1151 w.set_tim14_remap(bool_val);
1152 w.set_tim15_remap(bool_val);
1153 w.set_tim16_remap(bool_val);
1154 w.set_tim17_remap(bool_val);
1155 });
1156}
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index cb63b3374..f800769ab 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -103,7 +103,7 @@ define_peris!(
103 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2, 103 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
104 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;}, 104 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
105); 105);
106#[cfg(feature = "stm32f103c8")] 106#[cfg(any(feature = "stm32f100rd", feature = "stm32f103c8", feature = "stm32f107vc"))]
107define_peris!( 107define_peris!(
108 UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5, 108 UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5,
109 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2, 109 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,