Skip to content

Commit eb3aef7

Browse files
committed
Add I2C fast mode plus enable function to SysCfg. Added I2C fast mode plus example using an AS5600 magnetic angle sensor
1 parent a6369ca commit eb3aef7

File tree

3 files changed

+129
-3
lines changed

3 files changed

+129
-3
lines changed

Cargo.toml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ embedded-sdmmc = "0.3.0"
7474
usb-device = { version = "0.3.2", features = ["defmt"] }
7575
usbd-serial = "0.2.2"
7676
rand = { version = "0.9", default-features = false }
77+
as5600 = "0.8.0"
7778

7879
#TODO: Separate feature sets
7980
[features]
@@ -84,9 +85,23 @@ usb = ["dep:stm32-usbd"]
8485
stm32g431 = ["stm32g4/stm32g431", "cat2"]
8586
stm32g441 = ["stm32g4/stm32g441", "cat2"]
8687
stm32g473 = ["stm32g4/stm32g473", "cat3", "adc3", "adc4", "adc5"]
87-
stm32g474 = ["stm32g4/stm32g474", "cat3", "adc3", "adc4", "adc5", "stm32-hrtim/stm32g474"]
88+
stm32g474 = [
89+
"stm32g4/stm32g474",
90+
"cat3",
91+
"adc3",
92+
"adc4",
93+
"adc5",
94+
"stm32-hrtim/stm32g474",
95+
]
8896
stm32g483 = ["stm32g4/stm32g483", "cat3", "adc3", "adc4", "adc5"]
89-
stm32g484 = ["stm32g4/stm32g484", "cat3", "adc3", "adc4", "adc5", "stm32-hrtim/stm32g484"]
97+
stm32g484 = [
98+
"stm32g4/stm32g484",
99+
"cat3",
100+
"adc3",
101+
"adc4",
102+
"adc5",
103+
"stm32-hrtim/stm32g484",
104+
]
90105
stm32g491 = ["stm32g4/stm32g491", "cat4", "adc3"]
91106
stm32g4a1 = ["stm32g4/stm32g4a1", "cat4", "adc3"]
92107

@@ -108,7 +123,7 @@ defmt = [
108123
"embedded-hal/defmt-03",
109124
"embedded-io/defmt-03",
110125
"embedded-test/defmt",
111-
"stm32-hrtim?/defmt"
126+
"stm32-hrtim?/defmt",
112127
]
113128
cordic = ["dep:fixed"]
114129
adc3 = []

examples/i2c-fmp-as5600.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//! I2C Fast Mode Plus example with an AS5600 magnetic angle sensor.
2+
//!
3+
//! This example expects the AS5600 to be connected to the I2C bus on PB7 (SDA) and PA15 (SCL),
4+
//! and a 24MHz HSE oscillator to configure the PLL for 168MHz system clock.
5+
//!
6+
//! The I2C bus is configured with Fast Mode Plus (FMP) enabled in SysCfg, and a 1MHz I2C clock rate.
7+
//!
8+
//! ```DEFMT_LOG=debug cargo run --release --example rand --features stm32g431,defmt -- --chip STM32G431KBTx```
9+
10+
#![deny(warnings)]
11+
#![deny(unsafe_code)]
12+
#![no_main]
13+
#![no_std]
14+
15+
use fugit::HertzU32 as Hertz;
16+
use hal::prelude::*;
17+
use hal::rcc::SysClockSrc;
18+
use hal::stm32;
19+
use hal::time::RateExtU32;
20+
use stm32g4xx_hal as hal;
21+
use stm32g4xx_hal::syscfg::SysCfgExt;
22+
23+
use as5600::As5600;
24+
use cortex_m_rt::entry;
25+
26+
#[macro_use]
27+
mod utils;
28+
use utils::logger::error;
29+
use utils::logger::info;
30+
31+
#[entry]
32+
fn main() -> ! {
33+
utils::logger::init();
34+
35+
let dp = stm32::Peripherals::take().expect("cannot take peripherals");
36+
//let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals");
37+
38+
let pwr_cfg = dp
39+
.PWR
40+
.constrain()
41+
.vos(stm32g4xx_hal::pwr::VoltageScale::Range1 { enable_boost: true })
42+
.freeze();
43+
44+
let pll_cfg = hal::rcc::PllConfig {
45+
mux: hal::rcc::PllSrc::HSE(Hertz::MHz(24)),
46+
m: hal::rcc::PllMDiv::DIV_2,
47+
n: hal::rcc::PllNMul::MUL_28,
48+
r: Some(hal::rcc::PllRDiv::DIV_2),
49+
q: None,
50+
p: None,
51+
};
52+
53+
info!("Configuring PLL");
54+
let rcc_cfg = hal::rcc::Config::new(SysClockSrc::PLL)
55+
.boost(true)
56+
.pll_cfg(pll_cfg);
57+
58+
let mut rcc = dp.RCC.freeze(rcc_cfg, pwr_cfg);
59+
info!("System clock frequency: {}", rcc.clocks.sys_clk.to_Hz());
60+
61+
let gpioa = dp.GPIOA.split(&mut rcc);
62+
let gpiob = dp.GPIOB.split(&mut rcc);
63+
64+
let sda = gpiob.pb7.into_alternate_open_drain();
65+
let scl = gpioa.pa15.into_alternate_open_drain();
66+
67+
let mut syscfg = dp.SYSCFG.constrain(&mut rcc);
68+
69+
// Enable Fast Mode Plus for I2C1
70+
syscfg.i2c_fmp_enable::<1>(true);
71+
72+
// Configure I2C for 1MHz
73+
let i2c = dp.I2C1.i2c(sda, scl, 1.MHz(), &mut rcc);
74+
75+
let mut as5600 = As5600::new(i2c);
76+
77+
loop {
78+
match as5600.angle() {
79+
Ok(angle) => {
80+
// Convert angle to degrees
81+
let angle_degrees = angle as f32 * 360.0 / 4096.0;
82+
info!("Angle: {}°", angle_degrees);
83+
}
84+
Err(e) => match e {
85+
as5600::error::Error::Communication(_) => error!("I2C communication error"),
86+
as5600::error::Error::Status(_error) => error!("AS5600 status error"),
87+
as5600::error::Error::Configuration(_error) => error!("AS5600 configuration error"),
88+
_ => error!("Other AS5600 error"),
89+
},
90+
}
91+
}
92+
}

src/syscfg.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,22 @@ impl Deref for SysCfg {
2727
&self.0
2828
}
2929
}
30+
31+
impl SysCfg {
32+
/// Enable/disable I2C fast mode plus on the I2C bus index provided as a const generic parameter.
33+
///
34+
/// Pins that are configured as I2C alternate functions will be configured as fast mode plus.
35+
/// The alternate function mode of the pin must be set before FMP is enabled in SysCfg.
36+
///
37+
/// When FM+ mode is activated on a pin, the GPIO speed configuration (OSPEEDR) is is ignored and overridden.
38+
///
39+
pub fn i2c_fmp_enable<const BUS: u8>(&mut self, en: bool) {
40+
match BUS {
41+
1 => (*self).cfgr1().modify(|_, w| w.i2c1_fmp().bit(en)),
42+
2 => (*self).cfgr1().modify(|_, w| w.i2c2_fmp().bit(en)),
43+
3 => (*self).cfgr1().modify(|_, w| w.i2c3_fmp().bit(en)),
44+
4 => (*self).cfgr1().modify(|_, w| w.i2c4_fmp().bit(en)),
45+
_ => panic!("Invalid I2C bus"),
46+
};
47+
}
48+
}

0 commit comments

Comments
 (0)