Skip to content

Commit a959593

Browse files
authored
Merge pull request #6 from david-sawatzke/stm32f030_v2
Add more peripherals for the stm32f030
2 parents 7f7a7d6 + 5f7e6a6 commit a959593

File tree

6 files changed

+447
-298
lines changed

6 files changed

+447
-298
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ stm32f042 = ["stm32f0/stm32f0x2"]
5151
stm32f030 = ["stm32f0/stm32f0x0"]
5252
stm32f030x4 = ["stm32f030x6"]
5353
stm32f030x6 = ["stm32f030"]
54-
stm32f030x8 = ["stm32f030", "stm32f0/stm32f0x0"]
55-
stm32f030xc = ["stm32f030", "stm32f0/stm32f0x0"]
54+
stm32f030x8 = ["stm32f030"]
55+
stm32f030xc = ["stm32f030"]
5656

5757
[profile.dev]
5858
debug = true

src/gpio.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -564,12 +564,10 @@ gpio!(GPIOC, gpioc, iopcen, PC, [
564564
PC15: (pb15, 15, Input<Floating>),
565565
]);
566566

567-
// TODO Check if the bit is implemented yet
568-
// In the device crate the iopden bit is missing, so it won't compile
569-
// #[cfg(feature = "stm32f030")]
570-
// gpio!(GPIOD, gpiod, iopden, PD, [
571-
// PD2: (pd2, 2, Input<Floating>),
572-
// ]);
567+
#[cfg(feature = "stm32f030")]
568+
gpio!(GPIOD, gpiod, iopden, PD, [
569+
PD2: (pd2, 2, Input<Floating>),
570+
]);
573571

574572
#[cfg(feature = "stm32f042")]
575573
gpio!(GPIOF, gpiof, iopfen, PF, [

src/i2c.rs

+125-53
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,134 @@
1-
#[cfg(feature = "stm32f042")]
2-
use crate::stm32::{I2C1, RCC};
1+
use core::ops::Deref;
32

3+
use crate::stm32;
44
use embedded_hal::blocking::i2c::{Write, WriteRead};
55

6-
use core::cmp;
7-
#[cfg(feature = "stm32f042")]
8-
use crate::gpio::gpioa::{PA10, PA11, PA12, PA9};
9-
#[cfg(feature = "stm32f042")]
10-
use crate::gpio::gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9};
11-
#[cfg(feature = "stm32f042")]
12-
use crate::gpio::gpiof::{PF0, PF1};
13-
#[cfg(feature = "stm32f042")]
14-
use crate::gpio::{Alternate, AF1, AF4, AF5};
6+
use crate::gpio::*;
157
use crate::time::{KiloHertz, U32Ext};
8+
use core::cmp;
169

1710
/// I2C abstraction
18-
pub struct I2c<I2C, PINS> {
11+
pub struct I2c<I2C, SCLPIN, SDAPIN> {
1912
i2c: I2C,
20-
pins: PINS,
13+
pins: (SCLPIN, SDAPIN),
2114
}
2215

23-
pub trait Pins<I2c> {}
24-
25-
#[cfg(feature = "stm32f042")]
26-
impl Pins<I2C1> for (PA9<Alternate<AF4>>, PA10<Alternate<AF4>>) {}
27-
#[cfg(feature = "stm32f042")]
28-
impl Pins<I2C1> for (PA11<Alternate<AF5>>, PA12<Alternate<AF5>>) {}
29-
#[cfg(feature = "stm32f042")]
30-
impl Pins<I2C1> for (PB6<Alternate<AF1>>, PB7<Alternate<AF1>>) {}
31-
#[cfg(feature = "stm32f042")]
32-
impl Pins<I2C1> for (PB8<Alternate<AF1>>, PB9<Alternate<AF1>>) {}
33-
#[cfg(feature = "stm32f042")]
34-
impl Pins<I2C1> for (PB10<Alternate<AF1>>, PB11<Alternate<AF1>>) {}
35-
#[cfg(feature = "stm32f042")]
36-
impl Pins<I2C1> for (PB13<Alternate<AF5>>, PB14<Alternate<AF5>>) {}
37-
#[cfg(feature = "stm32f042")]
38-
impl Pins<I2C1> for (PF1<Alternate<AF1>>, PF0<Alternate<AF1>>) {}
16+
pub trait SclPin<I2C> {}
17+
pub trait SdaPin<I2C> {}
18+
19+
macro_rules! i2c_pins {
20+
($($I2C:ident => {
21+
scl => [$($scl:ty),+ $(,)*],
22+
sda => [$($sda:ty),+ $(,)*],
23+
})+) => {
24+
$(
25+
$(
26+
impl SclPin<stm32::$I2C> for $scl {}
27+
)+
28+
$(
29+
impl SdaPin<stm32::$I2C> for $sda {}
30+
)+
31+
)+
32+
}
33+
}
34+
35+
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
36+
i2c_pins! {
37+
I2C1 => {
38+
scl => [gpioa::PA11<Alternate<AF5>>, gpiob::PB6<Alternate<AF1>>, gpiob::PB8<Alternate<AF1>>],
39+
sda => [gpioa::PA12<Alternate<AF5>>, gpiob::PB7<Alternate<AF1>>, gpiob::PB9<Alternate<AF1>>],
40+
}
41+
}
42+
#[cfg(any(
43+
feature = "stm32f042",
44+
feature = "stm32f030x6",
45+
feature = "stm32f030xc"
46+
))]
47+
i2c_pins! {
48+
I2C1 => {
49+
scl => [gpioa::PA9<Alternate<AF4>>],
50+
sda => [gpioa::PA10<Alternate<AF4>>],
51+
}
52+
}
53+
#[cfg(any(feature = "stm32f042", feature = "stm32f030x6"))]
54+
i2c_pins! {
55+
I2C1 => {
56+
scl => [gpiob::PB10<Alternate<AF1>>],
57+
sda => [gpiob::PB11<Alternate<AF1>>],
58+
}
59+
}
60+
#[cfg(any(feature = "stm32f042", feature = "stm32f030xc"))]
61+
i2c_pins! {
62+
I2C1 => {
63+
scl => [gpiob::PB13<Alternate<AF5>>, gpiof::PF1<Alternate<AF1>>],
64+
sda => [gpiob::PB14<Alternate<AF5>>, gpiof::PF0<Alternate<AF1>>],
65+
}
66+
}
67+
#[cfg(any(feature = "stm32f030x8", feature = "stm32f030xc"))]
68+
i2c_pins! {
69+
I2C2 => {
70+
scl => [gpiob::PB10<Alternate<AF1>>],
71+
sda => [gpiob::PB11<Alternate<AF1>>],
72+
}
73+
}
74+
#[cfg(feature = "stm32f030xc")]
75+
i2c_pins! {
76+
I2C2 => {
77+
scl => [gpiob::PB13<Alternate<AF5>>],
78+
sda => [gpiob::PB14<Alternate<AF5>>],
79+
}
80+
}
3981

4082
#[derive(Debug)]
4183
pub enum Error {
4284
OVERRUN,
4385
NACK,
4486
}
4587

46-
#[cfg(feature = "stm32f042")]
47-
impl<PINS> I2c<I2C1, PINS> {
48-
pub fn i2c1(i2c: I2C1, pins: PINS, speed: KiloHertz) -> Self
49-
where
50-
PINS: Pins<I2C1>,
51-
{
52-
// NOTE(unsafe) This executes only during initialisation
53-
let rcc = unsafe { &(*RCC::ptr()) };
54-
55-
/* Enable clock for I2C1 */
56-
rcc.apb1enr.modify(|_, w| w.i2c1en().set_bit());
57-
58-
/* Reset I2C1 */
59-
rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
60-
rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());
88+
macro_rules! i2c {
89+
($($I2C:ident: ($i2c:ident, $i2cXen:ident, $i2cXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
90+
$(
91+
use crate::stm32::$I2C;
92+
impl<SCLPIN, SDAPIN> I2c<$I2C, SCLPIN, SDAPIN> {
93+
pub fn $i2c(i2c: $I2C, pins: (SCLPIN, SDAPIN), speed: KiloHertz) -> Self
94+
where
95+
SCLPIN: SclPin<$I2C>,
96+
SDAPIN: SdaPin<$I2C>,
97+
{
98+
// NOTE(unsafe) This executes only during initialisation
99+
let rcc = unsafe { &(*stm32::RCC::ptr()) };
100+
101+
/* Enable clock for I2C */
102+
rcc.$apbenr.modify(|_, w| w.$i2cXen().set_bit());
103+
104+
/* Reset I2C */
105+
rcc.$apbrstr.modify(|_, w| w.$i2cXrst().set_bit());
106+
rcc.$apbrstr.modify(|_, w| w.$i2cXrst().clear_bit());
107+
I2c { i2c, pins }.i2c_init(speed)
108+
}
109+
}
110+
)+
111+
}
112+
}
113+
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
114+
i2c! {
115+
I2C1: (i2c1, i2c1en, i2c1rst, apb1enr, apb1rstr),
116+
}
117+
#[cfg(any(feature = "stm32f030xc", feature = "stm32f030xc"))]
118+
i2c! {
119+
I2C2: (i2c2, i2c2en, i2c2rst, apb1enr, apb1rstr),
120+
}
61121

122+
// It's s needed for the impls, but rustc doesn't recognize that
123+
#[allow(dead_code)]
124+
type I2cRegisterBlock = stm32::i2c1::RegisterBlock;
125+
impl<I2C, SCLPIN, SDAPIN> I2c<I2C, SCLPIN, SDAPIN>
126+
where
127+
I2C: Deref<Target = I2cRegisterBlock>,
128+
{
129+
fn i2c_init(self: Self, speed: KiloHertz) -> Self {
62130
/* Make sure the I2C unit is disabled so we can configure it */
63-
i2c.cr1.modify(|_, w| w.pe().clear_bit());
131+
self.i2c.cr1.modify(|_, w| w.pe().clear_bit());
64132

65133
// Calculate settings for I2C speed modes
66134
let presc;
@@ -88,7 +156,7 @@ impl<PINS> I2c<I2C1, PINS> {
88156
}
89157

90158
/* Enable I2C signal generator, and configure I2C for 400KHz full speed */
91-
i2c.timingr.write(|w| {
159+
self.i2c.timingr.write(|w| {
92160
w.presc()
93161
.bits(presc)
94162
.scldel()
@@ -102,12 +170,12 @@ impl<PINS> I2c<I2C1, PINS> {
102170
});
103171

104172
/* Enable the I2C processing */
105-
i2c.cr1.modify(|_, w| w.pe().set_bit());
173+
self.i2c.cr1.modify(|_, w| w.pe().set_bit());
106174

107-
I2c { i2c, pins }
175+
self
108176
}
109177

110-
pub fn release(self) -> (I2C1, PINS) {
178+
pub fn release(self) -> (I2C, (SCLPIN, SDAPIN)) {
111179
(self.i2c, self.pins)
112180
}
113181

@@ -136,8 +204,10 @@ impl<PINS> I2c<I2C1, PINS> {
136204
}
137205
}
138206

139-
#[cfg(feature = "stm32f042")]
140-
impl<PINS> WriteRead for I2c<I2C1, PINS> {
207+
impl<I2C, SCLPIN, SDAPIN> WriteRead for I2c<I2C, SCLPIN, SDAPIN>
208+
where
209+
I2C: Deref<Target = I2cRegisterBlock>,
210+
{
141211
type Error = Error;
142212

143213
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
@@ -214,8 +284,10 @@ impl<PINS> WriteRead for I2c<I2C1, PINS> {
214284
}
215285
}
216286

217-
#[cfg(feature = "stm32f042")]
218-
impl<PINS> Write for I2c<I2C1, PINS> {
287+
impl<I2C, SCLPIN, SDAPIN> Write for I2c<I2C, SCLPIN, SDAPIN>
288+
where
289+
I2C: Deref<Target = I2cRegisterBlock>,
290+
{
219291
type Error = Error;
220292

221293
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {

0 commit comments

Comments
 (0)