Skip to content

Commit f8edcf4

Browse files
authored
Merge branch 'master' into stm32l4x6-otg
2 parents 1f85df1 + 35946d6 commit f8edcf4

File tree

5 files changed

+309
-78
lines changed

5 files changed

+309
-78
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,8 @@ required-features = ["rt", "stm32l4x2", "stm32-usbd"]
135135
[[example]]
136136
name = "otg_fs_serial"
137137
required-features = ["rt", "stm32l4x6", "otg_fs"]
138+
139+
[[example]]
140+
name = "i2c_write"
141+
required-features = ["stm32l4x1"]
142+

examples/spi_slave.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//! Interfacing the on-board L3GD20 (gyroscope)
2+
#![deny(unsafe_code)]
3+
// #![deny(warnings)]
4+
#![no_main]
5+
#![no_std]
6+
7+
#[macro_use(entry, exception)]
8+
extern crate cortex_m_rt as rt;
9+
extern crate cortex_m;
10+
extern crate embedded_hal as ehal;
11+
extern crate panic_semihosting;
12+
extern crate stm32l4xx_hal as hal;
13+
14+
use crate::ehal::spi::{Mode, Phase, Polarity};
15+
use crate::hal::prelude::*;
16+
use crate::hal::spi::Spi;
17+
use crate::rt::ExceptionFrame;
18+
use cortex_m::asm;
19+
20+
/// SPI mode
21+
pub const MODE: Mode = Mode {
22+
phase: Phase::CaptureOnFirstTransition,
23+
polarity: Polarity::IdleLow,
24+
};
25+
26+
#[entry]
27+
fn main() -> ! {
28+
let p = hal::stm32::Peripherals::take().unwrap();
29+
30+
let mut flash = p.FLASH.constrain();
31+
let mut rcc = p.RCC.constrain();
32+
let mut pwr = p.PWR.constrain(&mut rcc.apb1r1);
33+
34+
// TRY the other clock configuration
35+
// let clocks = rcc.cfgr.freeze(&mut flash.acr);
36+
let _clocks = rcc
37+
.cfgr
38+
.sysclk(80.mhz())
39+
.pclk1(80.mhz())
40+
.pclk2(80.mhz())
41+
.freeze(&mut flash.acr, &mut pwr);
42+
43+
let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
44+
45+
// The `L3gd20` abstraction exposed by the `f3` crate requires a specific pin configuration to
46+
// be used and won't accept any configuration other than the one used here. Trying to use a
47+
// different pin configuration will result in a compiler error.
48+
let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
49+
let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
50+
let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
51+
52+
// clock speed is determined by the master
53+
let mut spi = Spi::spi1_slave(p.SPI1, (sck, miso, mosi), MODE, &mut rcc.apb2);
54+
55+
let mut data = [0x1];
56+
// this will block until the master starts the clock
57+
spi.transfer(&mut data).unwrap();
58+
59+
// when you reach this breakpoint you'll be able to inspect the variable `data` which contains the
60+
// data sent by the master
61+
asm::bkpt();
62+
63+
loop {
64+
continue;
65+
}
66+
}
67+
68+
#[exception]
69+
fn HardFault(ef: &ExceptionFrame) -> ! {
70+
panic!("{:#?}", ef);
71+
}

src/i2c.rs

Lines changed: 155 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
//! [stm32h7xx-hal](https://github.com/stm32-rs/stm32h7xx-hal) implementation,
33
//! as of 2021-02-25.
44
5-
use crate::gpio::{Alternate, OpenDrain, Output, AF4};
65
use crate::hal::blocking::i2c::{Read, Write, WriteRead};
7-
use crate::pac::{i2c1, I2C1, I2C2};
6+
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x2", feature = "stm32l4x6"))]
7+
use crate::pac::I2C4;
8+
use crate::pac::{i2c1, I2C1, I2C2, I2C3};
9+
810
use crate::rcc::{Clocks, APB1R1};
9-
#[cfg(any(feature = "stm32l4x5", feature = "stm32l4x6"))]
10-
use crate::stm32::I2C3;
1111
use crate::time::Hertz;
1212
use cast::{u16, u8};
1313
use core::ops::Deref;
@@ -31,7 +31,7 @@ pub enum Error {
3131
}
3232

3333
#[doc(hidden)]
34-
mod private {
34+
pub(self) mod private {
3535
pub trait Sealed {}
3636
}
3737

@@ -44,12 +44,12 @@ pub trait SdaPin<I2C>: private::Sealed {}
4444
macro_rules! pins {
4545
($spi:ident, $af:ident, SCL: [$($scl:ident),*], SDA: [$($sda:ident),*]) => {
4646
$(
47-
impl private::Sealed for $scl<Alternate<$af, Output<OpenDrain>>> {}
48-
impl SclPin<$spi> for $scl<Alternate<$af, Output<OpenDrain>>> {}
47+
impl super::private::Sealed for $scl<Alternate<$af, Output<OpenDrain>>> {}
48+
impl super::SclPin<$spi> for $scl<Alternate<$af, Output<OpenDrain>>> {}
4949
)*
5050
$(
51-
impl private::Sealed for $sda<Alternate<$af, Output<OpenDrain>>> {}
52-
impl SdaPin<$spi> for $sda<Alternate<$af, Output<OpenDrain>>> {}
51+
impl super::private::Sealed for $sda<Alternate<$af, Output<OpenDrain>>> {}
52+
impl super::SdaPin<$spi> for $sda<Alternate<$af, Output<OpenDrain>>> {}
5353
)*
5454
}
5555
}
@@ -60,6 +60,8 @@ pub struct I2c<I2C, PINS> {
6060
pins: PINS,
6161
}
6262

63+
// TODO review why StartCondition and State structs exists. Last
64+
// update to them was november 2020
6365
/// Start conditions that govern repeated sequential transfer
6466
#[derive(Debug, Clone)]
6567
enum StartCondition {
@@ -119,48 +121,40 @@ impl State {
119121
}
120122
}
121123

122-
impl<SCL, SDA> I2c<I2C1, (SCL, SDA)> {
123-
pub fn i2c1<F>(i2c: I2C1, pins: (SCL, SDA), freq: F, clocks: Clocks, apb1: &mut APB1R1) -> Self
124-
where
125-
F: Into<Hertz>,
126-
SCL: SclPin<I2C1>,
127-
SDA: SdaPin<I2C1>,
128-
{
129-
apb1.enr().modify(|_, w| w.i2c1en().set_bit());
130-
apb1.rstr().modify(|_, w| w.i2c1rst().set_bit());
131-
apb1.rstr().modify(|_, w| w.i2c1rst().clear_bit());
132-
Self::new(i2c, pins, freq, clocks)
133-
}
124+
macro_rules! hal {
125+
($i2c_type: ident, $enr: ident, $rstr: ident, $i2cX: ident, $i2cXen: ident, $i2cXrst: ident) => {
126+
impl<SCL, SDA> I2c<$i2c_type, (SCL, SDA)> {
127+
pub fn $i2cX<F>(
128+
i2c: $i2c_type,
129+
pins: (SCL, SDA),
130+
freq: F,
131+
clocks: Clocks,
132+
apb1: &mut APB1R1,
133+
) -> Self
134+
where
135+
F: Into<Hertz>,
136+
SCL: SclPin<$i2c_type>,
137+
SDA: SdaPin<$i2c_type>,
138+
{
139+
apb1.$enr().modify(|_, w| w.$i2cXen().set_bit());
140+
apb1.$rstr().modify(|_, w| w.$i2cXrst().set_bit());
141+
apb1.$rstr().modify(|_, w| w.$i2cXrst().clear_bit());
142+
Self::new(i2c, pins, freq, clocks)
143+
}
144+
}
145+
};
134146
}
135147

136-
impl<SCL, SDA> I2c<I2C2, (SCL, SDA)> {
137-
pub fn i2c2<F>(i2c: I2C2, pins: (SCL, SDA), freq: F, clocks: Clocks, apb1: &mut APB1R1) -> Self
138-
where
139-
F: Into<Hertz>,
140-
SCL: SclPin<I2C2>,
141-
SDA: SdaPin<I2C2>,
142-
{
143-
apb1.enr().modify(|_, w| w.i2c2en().set_bit());
144-
apb1.rstr().modify(|_, w| w.i2c2rst().set_bit());
145-
apb1.rstr().modify(|_, w| w.i2c2rst().clear_bit());
146-
Self::new(i2c, pins, freq, clocks)
147-
}
148-
}
148+
hal!(I2C1, enr, rstr, i2c1, i2c1en, i2c1rst);
149+
hal!(I2C2, enr, rstr, i2c2, i2c2en, i2c2rst);
150+
hal!(I2C3, enr, rstr, i2c3, i2c3en, i2c3rst);
149151

150-
#[cfg(any(feature = "stm32l4x5", feature = "stm32l4x6"))]
151-
impl<SCL, SDA> I2c<I2C3, (SCL, SDA)> {
152-
pub fn i2c3<F>(i2c: I2C3, pins: (SCL, SDA), freq: F, clocks: Clocks, apb1: &mut APB1R1) -> Self
153-
where
154-
F: Into<Hertz>,
155-
SCL: SclPin<I2C3>,
156-
SDA: SdaPin<I2C3>,
157-
{
158-
apb1.enr().modify(|_, w| w.i2c3en().set_bit());
159-
apb1.rstr().modify(|_, w| w.i2c3rst().set_bit());
160-
apb1.rstr().modify(|_, w| w.i2c3rst().clear_bit());
161-
Self::new(i2c, pins, freq, clocks)
162-
}
163-
}
152+
// This peripheral is not present on
153+
// STM32L471XX and STM32L431XX
154+
// STM32L432XX and STM32l442XX
155+
// STM32L486XX and STM32L476XX
156+
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x2", feature = "stm32l4x6"))]
157+
hal!(I2C4, enr2, rstr2, i2c4, i2c4en, i2c4rst);
164158

165159
impl<SCL, SDA, I2C> I2c<I2C, (SCL, SDA)>
166160
where
@@ -225,14 +219,26 @@ where
225219
(presc, scll, sclh, sdadel, scldel)
226220
};
227221

228-
let presc = u8(presc).unwrap();
222+
macro_rules! u8_or_panic {
223+
($value: expr, $message: literal) => {
224+
match u8($value) {
225+
Ok(value) => value,
226+
Err(_) => panic!($message),
227+
}
228+
};
229+
}
230+
231+
let presc = u8_or_panic!(presc, "I2C pres");
229232
assert!(presc < 16);
230-
let scldel = u8(scldel).unwrap();
233+
234+
let scldel = u8_or_panic!(scldel, "I2C scldel");
231235
assert!(scldel < 16);
232-
let sdadel = u8(sdadel).unwrap();
236+
237+
let sdadel = u8_or_panic!(sdadel, "I2C sdadel");
233238
assert!(sdadel < 16);
234-
let sclh = u8(sclh).unwrap();
235-
let scll = u8(scll).unwrap();
239+
240+
let sclh = u8_or_panic!(sclh, "I2C sclh");
241+
let scll = u8_or_panic!(scll, "I2C scll");
236242

237243
// Configure for "fast mode" (400 KHz)
238244
i2c.timingr.write(|w| {
@@ -472,35 +478,110 @@ where
472478
}
473479
}
474480

475-
use crate::gpio::gpioa::{PA10, PA9};
476-
use crate::gpio::gpiob::{PB10, PB11, PB6, PB7};
481+
#[cfg(feature = "stm32l4x1")]
482+
mod stm32l4x1_pins {
483+
use super::{I2C1, I2C2, I2C3, I2C4};
484+
use crate::gpio::*;
485+
use gpioa::{PA10, PA7, PA9};
486+
use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9};
487+
use gpioc::{PC0, PC1};
477488

478-
#[cfg(any(feature = "stm32l4x3", feature = "stm32l4x5", feature = "stm32l4x6"))]
479-
use crate::gpio::gpioc::{PC0, PC1};
489+
pins!(I2C1, AF4, SCL: [PB6, PB8], SDA: [PB7, PB9]);
480490

481-
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x3", feature = "stm32l4x6"))]
482-
use crate::gpio::gpiob::PB8;
491+
// Not on STM32L471XX
492+
pins!(I2C1, AF4, SCL: [PA9], SDA: [PA10]);
483493

484-
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x6"))]
485-
use crate::gpio::gpiob::{PB13, PB14, PB9};
494+
pins!(I2C2, AF4, SCL: [PB10, PB13], SDA: [PB11, PB14]);
486495

487-
pins!(I2C1, AF4,
488-
SCL: [PA9, PB6],
489-
SDA: [PA10, PB7]);
496+
pins!(I2C3, AF4, SCL: [PC0], SDA: [PC1]);
490497

491-
pins!(I2C2, AF4, SCL: [PB10], SDA: [PB11]);
498+
// Not on STM32L471XX
499+
pins!(I2C3, AF4, SCL: [PA7], SDA: [PB4]);
492500

493-
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x6"))]
494-
pins!(I2C1, AF4, SCL: [PB8], SDA: [PB9]);
501+
// Not on STM32L471XX and STM32L431XX
502+
pins!(I2C4, AF4, SCL: [PD12], SDA: [PD13]);
503+
pins!(I2C4, AF3, SCL: [PB10], SDA: [PB11]);
504+
}
495505

496-
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x6"))]
497-
pins!(I2C2, AF4, SCL: [PB13], SDA: [PB14]);
506+
#[cfg(feature = "stm32l4x2")]
507+
mod stm32l4x2_pins {
508+
use super::{I2C1, I2C2, I2C3, I2C4};
509+
use crate::gpio::*;
510+
use gpioa::{PA10, PA7, PA9};
511+
use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9};
512+
use gpioc::{PC0, PC1};
498513

499-
#[cfg(any(feature = "stm32l4x5", feature = "stm32l4x6"))]
500-
pins!(I2C3, AF4, SCL: [PC0], SDA: [PC1]);
514+
pins!(I2C1, AF4, SCL: [PA9, PB6], SDA: [PA10, PB7]);
501515

502-
#[cfg(feature = "stm32l4x3")]
503-
pins!(I2C1, AF4, SCL: [PB8], SDA: []);
516+
// Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
517+
pins!(I2C2, AF4, SCL: [PB8, PB10, PB13], SDA: [PB9, PB11, PB14]);
518+
519+
pins!(I2C3, AF4, SCL: [PA7], SDA: [PB4]);
520+
521+
// Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
522+
pins!(I2C3, AF4, SCL: [PC0], SDA: [PC1]);
523+
524+
// Technically not present on STM32L432XX and STM32l442XX (pins missing from ref. manual)
525+
// Not present on STM32L412XX and STM32L422XX
526+
pins!(I2C4, AF2, SCL: [PC0], SDA: [PC1]);
527+
pins!(I2C4, AF3, SCL: [PB10], SDA: [PB11]);
528+
pins!(I2C4, AF4, SCL: [PD12], SDA: [PD13]);
529+
}
504530

505531
#[cfg(feature = "stm32l4x3")]
506-
pins!(I2C2, AF4, SCL: [PC0], SDA: [PC1]);
532+
mod stm32l4x3_pins {
533+
use super::{I2C1, I2C2, I2C3};
534+
use crate::gpio::*;
535+
use gpioa::{PA10, PA7, PA9};
536+
use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9};
537+
use gpioc::{PC0, PC1};
538+
539+
pins!(I2C1, AF4, SCL: [PA9, PB6, PB8], SDA: [PA10, PB7, PB9]);
540+
541+
pins!(I2C2, AF4, SCL: [PB10, PB13], SDA: [PB11, PB14]);
542+
543+
pins!(I2C3, AF4, SCL: [PA7, PC0], SDA: [PB4, PC1]);
544+
}
545+
546+
#[cfg(feature = "stm32l4x5")]
547+
mod stm32l4x5_pins {
548+
use super::{I2C1, I2C2, I2C3};
549+
use crate::gpio::*;
550+
use gpiob::{PB10, PB11, PB13, PB14, PB6, PB7, PB8, PB9};
551+
use gpioc::{PC0, PC1};
552+
553+
pins!(I2C1, AF4, SCL: [PB6, PB8], SDA: [PB7, PB9]);
554+
555+
pins!(I2C2, AF4, SCL: [PB10, PB13], SDA: [PB11, PB14]);
556+
557+
pins!(I2C3, AF4, SCL: [PC0], SDA: [PC1]);
558+
}
559+
560+
#[cfg(feature = "stm32l4x6")]
561+
mod stm32l4x6_pins {
562+
use super::{I2C1, I2C2, I2C3, I2C4};
563+
use crate::gpio::*;
564+
use gpioa::PA7;
565+
use gpiob::{PB10, PB11, PB13, PB14, PB4, PB6, PB7, PB8, PB9};
566+
use gpioc::{PC0, PC1};
567+
use gpiod::{PD12, PD13};
568+
use gpiof::{PF0, PF1, PF14, PF15};
569+
use gpiog::{PG13, PG14, PG7, PG8};
570+
571+
pins!(I2C1, AF4, SCL: [PB6, PB8], SDA: [PB7, PB9]);
572+
573+
pins!(I2C2, AF4, SCL: [PB10, PB13, PF1], SDA: [PB11, PB14, PF0]);
574+
575+
pins!(I2C3, AF4, SCL: [PC0, PG7, PG14], SDA: [PC1, PG8, PG13]);
576+
577+
// Both not on STM32L486XX and STM32L476XX
578+
pins!(I2C3, AF4, SCL: [PA7], SDA: [PB4]);
579+
pins!(I2C4, AF4, SCL: [PD12, PF14], SDA: [PD13, PF15]);
580+
581+
// These are present on STM32L496XX and STM32L4A6xG, but the
582+
// PAC does not have gpioh, so we can't actually these pins
583+
// Both not on STM32L486XX and STM32L476XX
584+
// use gpioh::{PH4, PH5, PH7, PH8};
585+
// pins!(I2C2, AF4, SCL: [PH4], SDA: [PH5]);
586+
// pins!(I2C3, AF4, SCL: [PH7], SDA: [PH8]);
587+
}

src/rcc.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,18 @@ impl APB1R1 {
255255
// NOTE(unsafe) this proxy grants exclusive access to this register
256256
unsafe { &(*RCC::ptr()).apb1rstr1 }
257257
}
258+
259+
#[cfg(not(any(feature = "stm32l4x3", feature = "stm32l4x5")))]
260+
pub(crate) fn enr2(&mut self) -> &rcc::APB1ENR2 {
261+
// NOTE(unsafe) this proxy grants exclusive access to this register
262+
unsafe { &(*RCC::ptr()).apb1enr2 }
263+
}
264+
265+
#[cfg(not(any(feature = "stm32l4x3", feature = "stm32l4x5")))]
266+
pub(crate) fn rstr2(&mut self) -> &rcc::APB1RSTR2 {
267+
// NOTE(unsafe) this proxy grants exclusive access to this register
268+
unsafe { &(*RCC::ptr()).apb1rstr2 }
269+
}
258270
}
259271

260272
/// Advanced Peripheral Bus 1 (APB1) register 2 registers

0 commit comments

Comments
 (0)