Skip to content

Commit 25e0ebf

Browse files
authored
Merge pull request #4430 from fwolter/add-f1-remap
Add STM32F1 AFIO remap
2 parents 24902b9 + 23d5c7e commit 25e0ebf

40 files changed

+1762
-431
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
1818
"rust-analyzer.cargo.features": [
1919
// Comment out these features when working on the examples. Most example crates do not have any cargo features.
20-
"stm32f446re",
20+
"stm32f107rb",
2121
"time-driver-any",
2222
"unstable-pac",
2323
"exti",

ci.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,9 @@ cargo batch \
311311
--- build --release --manifest-path examples/boot/bootloader/stm32wba-dfu/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-stm32/stm32wba65ri,verify \
312312
--- build --release --manifest-path examples/boot/bootloader/stm32-dual-bank/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32h743zi \
313313
--- 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 \
314315
--- 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 \
315317
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --artifact-dir out/tests/stm32f429zi \
316318
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446re --artifact-dir out/tests/stm32f446re \
317319
--- 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
398400
rm out/tests/rpi-pico/pwm
399401
rm out/tests/rpi-pico/cyw43-perf
400402

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
402404
rm -rf out/tests/stm32c071rb
405+
rm -rf out/tests/stm32f100rd
406+
rm -rf out/tests/stm32f107vc
403407

404408
if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
405409
echo No teleprobe token found, skipping running HIL tests

embassy-stm32/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3030
- fix: Fix stm32h7rs init when using external flash via XSPI
3131
- feat: Add Adc::new_with_clock() to configure analog clock
3232
- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923))
33+
- feat: Added support for STM32F1 peripheral pin remapping (AFIO) ([#4430](https://github.com/embassy-rs/embassy/pull/4430))
3334

3435
## 0.3.0 - 2025-08-12
3536

embassy-stm32/build.rs

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,9 +1391,53 @@ fn main() {
13911391
})
13921392
}
13931393

1394-
g.extend(quote! {
1395-
pin_trait_impl!(#tr, #peri, #pin_name, #af);
1396-
})
1394+
let pin_trait_impl = if let Some(afio) = &p.afio {
1395+
let values = afio
1396+
.values
1397+
.iter()
1398+
.filter(|v| v.pins.contains(&pin.pin))
1399+
.map(|v| v.value)
1400+
.collect::<Vec<_>>();
1401+
1402+
if values.is_empty() {
1403+
None
1404+
} else {
1405+
let reg = format_ident!("{}", afio.register.to_lowercase());
1406+
let setter = format_ident!("set_{}", afio.field.to_lowercase());
1407+
let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) {
1408+
let values = values.iter().map(|&v| v > 0);
1409+
quote!(AfioRemapBool, [#(#values),*])
1410+
} else {
1411+
quote!(AfioRemap, [#(#values),*])
1412+
};
1413+
1414+
Some(quote! {
1415+
pin_trait_afio_impl!(#tr, #peri, #pin_name, {#reg, #setter, #type_and_values});
1416+
})
1417+
}
1418+
} else {
1419+
let peripherals_with_afio = [
1420+
"CAN",
1421+
"CEC",
1422+
"ETH",
1423+
"I2C",
1424+
"SPI",
1425+
"SUBGHZSPI",
1426+
"USART",
1427+
"UART",
1428+
"LPUART",
1429+
"TIM",
1430+
];
1431+
let not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) {
1432+
quote!(, crate::gpio::AfioRemapNotApplicable)
1433+
} else {
1434+
quote!()
1435+
};
1436+
1437+
Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af #not_applicable);))
1438+
};
1439+
1440+
g.extend(pin_trait_impl);
13971441
}
13981442

13991443
// ADC is special
@@ -1588,17 +1632,7 @@ fn main() {
15881632
let register = format_ident!("{}", remap_info.register.to_lowercase());
15891633
let setter = format_ident!("set_{}", remap_info.field.to_lowercase());
15901634

1591-
let field_metadata = METADATA
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 {
1635+
let value = if is_bool_field("SYSCFG", &remap_info.register, &remap_info.field) {
16021636
let bool_value = format_ident!("{}", remap_info.value > 0);
16031637
quote!(#bool_value)
16041638
} else {
@@ -2300,3 +2334,17 @@ fn gcd(a: u32, b: u32) -> u32 {
23002334
}
23012335
gcd(b, a % b)
23022336
}
2337+
2338+
fn is_bool_field(peripheral: &str, register: &str, field: &str) -> bool {
2339+
let field_metadata = METADATA
2340+
.peripherals
2341+
.iter()
2342+
.filter(|p| p.name == peripheral)
2343+
.flat_map(|p| p.registers.as_ref().unwrap().ir.fieldsets.iter())
2344+
.filter(|f| f.name.eq_ignore_ascii_case(register))
2345+
.flat_map(|f| f.fields.iter())
2346+
.find(|f| f.name.eq_ignore_ascii_case(field))
2347+
.unwrap();
2348+
2349+
field_metadata.bit_size == 1
2350+
}

embassy-stm32/src/can/bxcan/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ pub enum TryWriteError {
181181
impl<'d> Can<'d> {
182182
/// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
183183
/// You must call [Can::enable_non_blocking] to use the peripheral.
184-
pub fn new<T: Instance>(
184+
pub fn new<T: Instance, #[cfg(afio)] A>(
185185
_peri: Peri<'d, T>,
186-
rx: Peri<'d, impl RxPin<T>>,
187-
tx: Peri<'d, impl TxPin<T>>,
186+
rx: Peri<'d, if_afio!(impl RxPin<T, A>)>,
187+
tx: Peri<'d, if_afio!(impl TxPin<T, A>)>,
188188
_irqs: impl interrupt::typelevel::Binding<T::TXInterrupt, TxInterruptHandler<T>>
189189
+ interrupt::typelevel::Binding<T::RX0Interrupt, Rx0InterruptHandler<T>>
190190
+ interrupt::typelevel::Binding<T::RX1Interrupt, Rx1InterruptHandler<T>>
@@ -194,8 +194,8 @@ impl<'d> Can<'d> {
194194
let info = T::info();
195195
let regs = &T::info().regs;
196196

197-
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
198-
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
197+
set_as_af!(rx, AfType::input(Pull::None));
198+
set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh));
199199

200200
rcc::enable_and_reset::<T>();
201201

@@ -229,8 +229,8 @@ impl<'d> Can<'d> {
229229
info.sce_interrupt.enable();
230230
}
231231

232-
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
233-
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
232+
set_as_af!(rx, AfType::input(Pull::None));
233+
set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh));
234234

235235
Registers(T::regs()).leave_init_mode();
236236

@@ -1218,8 +1218,8 @@ foreach_peripheral!(
12181218
};
12191219
);
12201220

1221-
pin_trait!(RxPin, Instance);
1222-
pin_trait!(TxPin, Instance);
1221+
pin_trait!(RxPin, Instance, @A);
1222+
pin_trait!(TxPin, Instance, @A);
12231223

12241224
trait Index {
12251225
fn index(&self) -> usize;

embassy-stm32/src/can/fdcan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@ impl<'d> CanConfigurator<'d> {
185185
+ interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
186186
+ 'd,
187187
) -> CanConfigurator<'d> {
188-
rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
189-
tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
188+
set_as_af!(rx, AfType::input(Pull::None));
189+
set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh));
190190

191191
rcc::enable_and_reset::<T>();
192192

embassy-stm32/src/dcmi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ macro_rules! config_pins {
108108
($($pin:ident),*) => {
109109
critical_section::with(|_| {
110110
$(
111-
$pin.set_as_af($pin.af_num(), AfType::input(Pull::None));
111+
set_as_af!($pin, AfType::input(Pull::None));
112112
)*
113113
})
114114
};

embassy-stm32/src/dsihost.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'d, T: Instance> DsiHost<'d, T> {
7878
rcc::enable_and_reset::<T>();
7979

8080
// Set Tearing Enable pin according to CubeMx example
81-
te.set_as_af(te.af_num(), AfType::output(OutputType::PushPull, Speed::Low));
81+
set_as_af!(te, AfType::output(OutputType::PushPull, Speed::Low));
8282
/*
8383
T::regs().wcr().modify(|w| {
8484
w.set_dsien(true);

embassy-stm32/src/eth/mod.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,19 @@ impl SealedInstance for crate::peripherals::ETH {
209209
}
210210
impl Instance for crate::peripherals::ETH {}
211211

212-
pin_trait!(RXClkPin, Instance);
213-
pin_trait!(TXClkPin, Instance);
214-
pin_trait!(RefClkPin, Instance);
215-
pin_trait!(MDIOPin, Instance);
216-
pin_trait!(MDCPin, Instance);
217-
pin_trait!(RXDVPin, Instance);
218-
pin_trait!(CRSPin, Instance);
219-
pin_trait!(RXD0Pin, Instance);
220-
pin_trait!(RXD1Pin, Instance);
221-
pin_trait!(RXD2Pin, Instance);
222-
pin_trait!(RXD3Pin, Instance);
223-
pin_trait!(TXD0Pin, Instance);
224-
pin_trait!(TXD1Pin, Instance);
225-
pin_trait!(TXD2Pin, Instance);
226-
pin_trait!(TXD3Pin, Instance);
227-
pin_trait!(TXEnPin, Instance);
212+
pin_trait!(RXClkPin, Instance, @A);
213+
pin_trait!(TXClkPin, Instance, @A);
214+
pin_trait!(RefClkPin, Instance, @A);
215+
pin_trait!(MDIOPin, Instance, @A);
216+
pin_trait!(MDCPin, Instance, @A);
217+
pin_trait!(RXDVPin, Instance, @A);
218+
pin_trait!(CRSPin, Instance, @A);
219+
pin_trait!(RXD0Pin, Instance, @A);
220+
pin_trait!(RXD1Pin, Instance, @A);
221+
pin_trait!(RXD2Pin, Instance, @A);
222+
pin_trait!(RXD3Pin, Instance, @A);
223+
pin_trait!(TXD0Pin, Instance, @A);
224+
pin_trait!(TXD1Pin, Instance, @A);
225+
pin_trait!(TXD2Pin, Instance, @A);
226+
pin_trait!(TXD3Pin, Instance, @A);
227+
pin_trait!(TXEnPin, Instance, @A);

embassy-stm32/src/eth/v1/mod.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ macro_rules! config_in_pins {
6969
critical_section::with(|_| {
7070
$(
7171
// TODO properly create a set_as_input function
72-
$pin.set_as_af($pin.af_num(), AfType::input(Pull::None));
72+
set_as_af!($pin, AfType::input(Pull::None));
7373
)*
7474
})
7575
}
@@ -80,7 +80,7 @@ macro_rules! config_af_pins {
8080
($($pin:ident),*) => {
8181
critical_section::with(|_| {
8282
$(
83-
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
83+
set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh));
8484
)*
8585
})
8686
};
@@ -91,27 +91,27 @@ macro_rules! config_pins {
9191
($($pin:ident),*) => {
9292
critical_section::with(|_| {
9393
$(
94-
$pin.set_as_af($pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
94+
set_as_af!($pin, AfType::output(OutputType::PushPull, Speed::VeryHigh));
9595
)*
9696
})
9797
};
9898
}
9999

100100
impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
101101
/// 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, #[cfg(afio)] A>(
103103
queue: &'d mut PacketQueue<TX, RX>,
104104
peri: Peri<'d, T>,
105105
irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
106-
ref_clk: Peri<'d, impl RefClkPin<T>>,
107-
mdio: Peri<'d, impl MDIOPin<T>>,
108-
mdc: Peri<'d, impl MDCPin<T>>,
109-
crs: Peri<'d, impl CRSPin<T>>,
110-
rx_d0: Peri<'d, impl RXD0Pin<T>>,
111-
rx_d1: Peri<'d, impl RXD1Pin<T>>,
112-
tx_d0: Peri<'d, impl TXD0Pin<T>>,
113-
tx_d1: Peri<'d, impl TXD1Pin<T>>,
114-
tx_en: Peri<'d, impl TXEnPin<T>>,
106+
ref_clk: Peri<'d, if_afio!(impl RefClkPin<T, A>)>,
107+
mdio: Peri<'d, if_afio!(impl MDIOPin<T, A>)>,
108+
mdc: Peri<'d, if_afio!(impl MDCPin<T, A>)>,
109+
crs: Peri<'d, if_afio!(impl CRSPin<T, A>)>,
110+
rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>,
111+
rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>,
112+
tx_d0: Peri<'d, if_afio!(impl TXD0Pin<T, A>)>,
113+
tx_d1: Peri<'d, if_afio!(impl TXD1Pin<T, A>)>,
114+
tx_en: Peri<'d, if_afio!(impl TXEnPin<T, A>)>,
115115
phy: P,
116116
mac_addr: [u8; 6],
117117
) -> Self {
@@ -289,24 +289,24 @@ impl<'d, T: Instance, P: Phy> Ethernet<'d, T, P> {
289289
}
290290

291291
/// Create a new MII ethernet driver using 14 pins.
292-
pub fn new_mii<const TX: usize, const RX: usize>(
292+
pub fn new_mii<const TX: usize, const RX: usize, #[cfg(afio)] A>(
293293
queue: &'d mut PacketQueue<TX, RX>,
294294
peri: Peri<'d, T>,
295295
irq: impl interrupt::typelevel::Binding<interrupt::typelevel::ETH, InterruptHandler> + 'd,
296-
rx_clk: Peri<'d, impl RXClkPin<T>>,
297-
tx_clk: Peri<'d, impl TXClkPin<T>>,
298-
mdio: Peri<'d, impl MDIOPin<T>>,
299-
mdc: Peri<'d, impl MDCPin<T>>,
300-
rxdv: Peri<'d, impl RXDVPin<T>>,
301-
rx_d0: Peri<'d, impl RXD0Pin<T>>,
302-
rx_d1: Peri<'d, impl RXD1Pin<T>>,
303-
rx_d2: Peri<'d, impl RXD2Pin<T>>,
304-
rx_d3: Peri<'d, impl RXD3Pin<T>>,
305-
tx_d0: Peri<'d, impl TXD0Pin<T>>,
306-
tx_d1: Peri<'d, impl TXD1Pin<T>>,
307-
tx_d2: Peri<'d, impl TXD2Pin<T>>,
308-
tx_d3: Peri<'d, impl TXD3Pin<T>>,
309-
tx_en: Peri<'d, impl TXEnPin<T>>,
296+
rx_clk: Peri<'d, if_afio!(impl RXClkPin<T, A>)>,
297+
tx_clk: Peri<'d, if_afio!(impl TXClkPin<T, A>)>,
298+
mdio: Peri<'d, if_afio!(impl MDIOPin<T, A>)>,
299+
mdc: Peri<'d, if_afio!(impl MDCPin<T, A>)>,
300+
rxdv: Peri<'d, if_afio!(impl RXDVPin<T, A>)>,
301+
rx_d0: Peri<'d, if_afio!(impl RXD0Pin<T, A>)>,
302+
rx_d1: Peri<'d, if_afio!(impl RXD1Pin<T, A>)>,
303+
rx_d2: Peri<'d, if_afio!(impl RXD2Pin<T, A>)>,
304+
rx_d3: Peri<'d, if_afio!(impl RXD3Pin<T, A>)>,
305+
tx_d0: Peri<'d, if_afio!(impl TXD0Pin<T, A>)>,
306+
tx_d1: Peri<'d, if_afio!(impl TXD1Pin<T, A>)>,
307+
tx_d2: Peri<'d, if_afio!(impl TXD2Pin<T, A>)>,
308+
tx_d3: Peri<'d, if_afio!(impl TXD3Pin<T, A>)>,
309+
tx_en: Peri<'d, if_afio!(impl TXEnPin<T, A>)>,
310310
phy: P,
311311
mac_addr: [u8; 6],
312312
) -> Self {

0 commit comments

Comments
 (0)