Skip to content

Commit a72e4c5

Browse files
authored
Merge pull request #30 from mathk/master
* Adds GPIOE support * Added MSI clock support.
2 parents d66ac33 + e2f26b7 commit a72e4c5

File tree

7 files changed

+152
-29
lines changed

7 files changed

+152
-29
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ edition = "2018"
2323
[dependencies]
2424
cortex-m = "0.5.8"
2525
nb = "0.1.1"
26-
stm32l4 = "0.5.0"
26+
stm32l4 = "0.6.0"
2727
as-slice = "0.1"
2828

2929
[dependencies.cast]
@@ -52,6 +52,7 @@ stm32l4x2 = ["stm32l4/stm32l4x2"]
5252
stm32l4x3 = ["stm32l4/stm32l4x3"]
5353
stm32l4x5 = ["stm32l4/stm32l4x5"]
5454
stm32l4x6 = ["stm32l4/stm32l4x6"]
55+
stm32l47x = ["stm32l4x6"]
5556
unproven = ["embedded-hal/unproven"]
5657

5758
[dev-dependencies]

examples/serial_vcom.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,26 @@ fn main() -> ! {
2727

2828
let mut flash = p.FLASH.constrain();
2929
let mut rcc = p.RCC.constrain();
30-
let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
30+
// let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
3131
// let mut gpiob = p.GPIOB.split(&mut rcc.ahb2);
32+
let mut gpiod = p.GPIOD.split(&mut rcc.ahb2);
3233

3334
// clock configuration using the default settings (all clocks run at 8 MHz)
3435
let clocks = rcc.cfgr.freeze(&mut flash.acr);
3536
// TRY this alternate clock configuration (clocks run at nearly the maximum frequency)
3637
// let clocks = rcc.cfgr.sysclk(64.mhz()).pclk1(32.mhz()).freeze(&mut flash.acr);
3738

38-
let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
39-
// let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
39+
//let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
40+
// let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
41+
let tx = gpiod.pd5.into_af7(&mut gpiod.moder, &mut gpiod.afrl);
4042

41-
let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
42-
// let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
43+
// let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
44+
// let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
45+
let rx = gpiod.pd6.into_af7(&mut gpiod.moder, &mut gpiod.afrl);
4346

4447
// TRY using a different USART peripheral here
45-
let serial = Serial::usart2(p.USART2, (tx, rx), 9_600.bps(), clocks, &mut rcc.apb1r1);
46-
let (mut tx, _) = serial.split();
48+
let serial = Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb1r1);
49+
let (mut tx, mut rx) = serial.split();
4750

4851
let sent = b'X';
4952

@@ -58,10 +61,11 @@ fn main() -> ! {
5861
block!(tx.write(sent)).ok();
5962
block!(tx.write(sent)).ok();
6063

61-
// when using virtual com port for recieve, causes a framing error
62-
// let received = block!(rx.read()).unwrap();
64+
// when using virtual com port for recieve can causes a framing error
65+
// On the stm32l476 discovery it is working fine at 115200 baud
66+
let received = block!(rx.read()).unwrap();
6367

64-
// assert_eq!(received, sent);
68+
assert_eq!(received, sent);
6569

6670
// if all goes well you should reach this breakpoint
6771
asm::bkpt();

src/gpio.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,23 @@ gpio!(GPIOB, gpiob, gpiob, gpioben, gpiobrst, PBx, [
587587
PB5: (pb5, 5, Input<Floating>, AFRL),
588588
PB6: (pb6, 6, Input<Floating>, AFRL),
589589
PB7: (pb7, 7, Input<Floating>, AFRL),
590+
PB8: (pb8, 8, Input<Floating>, AFRH),
591+
PB9: (pb9, 9, Input<Floating>, AFRH),
592+
PB10: (pb10, 10, Input<Floating>, AFRH),
593+
PB11: (pb11, 11, Input<Floating>, AFRH),
590594
]);
591595

596+
gpio!(GPIOD, gpiod, gpioc, gpioden, gpiodrst, PDx, [
597+
PD0: (pd0, 0, Input<Floating>, AFRL),
598+
PD1: (pd1, 1, Input<Floating>, AFRL),
599+
PD2: (pd2, 2, Input<Floating>, AFRL),
600+
PD3: (pd3, 3, Input<Floating>, AFRL),
601+
PD4: (pd4, 4, Input<Floating>, AFRL),
602+
PD5: (pd5, 5, Input<Floating>, AFRL),
603+
PD6: (pd6, 6, Input<Floating>, AFRL),
604+
PD7: (pd7, 7, Input<Floating>, AFRL),
605+
PD8: (pd8, 8, Input<Floating>, AFRH),
606+
]);
592607

593608
gpio!(GPIOE, gpioe, gpioc, gpioeen, gpioerst, PEx, [
594609
PE0: (pe0, 0, Input<Floating>, AFRL),
@@ -599,5 +614,5 @@ gpio!(GPIOE, gpioe, gpioc, gpioeen, gpioerst, PEx, [
599614
PE5: (pe5, 5, Input<Floating>, AFRL),
600615
PE6: (pe6, 6, Input<Floating>, AFRL),
601616
PE7: (pe7, 7, Input<Floating>, AFRL),
602-
PE8: (pe8, 8, Input<Floating>, AFRL),
617+
PE8: (pe8, 8, Input<Floating>, AFRH),
603618
]);

src/i2c.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use cast::u8;
44
use crate::stm32::{I2C1, I2C2};
55

66
use crate::gpio::gpioa::{PA10, PA9};
7-
use crate::gpio::gpiob::{PB6, PB7};
7+
use crate::gpio::gpiob::{PB6, PB7, PB10, PB11};
88
use crate::gpio::{AF4, Alternate, OpenDrain, Output};
99
use crate::hal::blocking::i2c::{Write, WriteRead, Read};
1010
use crate::rcc::{APB1R1, Clocks};
@@ -39,6 +39,8 @@ unsafe impl SclPin<I2C1> for PA9<Alternate<AF4, Output<OpenDrain>>> {}
3939
unsafe impl SdaPin<I2C1> for PA10<Alternate<AF4, Output<OpenDrain>>> {}
4040
unsafe impl SclPin<I2C1> for PB6<Alternate<AF4, Output<OpenDrain>>> {}
4141
unsafe impl SdaPin<I2C1> for PB7<Alternate<AF4, Output<OpenDrain>>> {}
42+
unsafe impl SclPin<I2C2> for PB10<Alternate<AF4, Output<OpenDrain>>> {}
43+
unsafe impl SdaPin<I2C2> for PB11<Alternate<AF4, Output<OpenDrain>>> {}
4244

4345
/// I2C peripheral operating in master mode
4446
pub struct I2c<I2C, PINS> {
@@ -56,7 +58,7 @@ macro_rules! busy_wait {
5658
} else if isr.arlo().bit_is_set() {
5759
return Err(Error::Arbitration);
5860
} else if isr.nackf().bit_is_set() {
59-
return Err(Error::Nack);
61+
return Err(Error::Nack);
6062
} else if isr.$flag().bit_is_set() {
6163
break;
6264
} else {
@@ -313,4 +315,4 @@ macro_rules! hal {
313315
hal! {
314316
I2C1: (i2c1, i2c1en, i2c1rst),
315317
I2C2: (i2c2, i2c2en, i2c2rst),
316-
}
318+
}

src/rcc.rs

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,42 @@ use crate::stm32::{rcc, RCC};
88
use crate::flash::ACR;
99
use crate::time::Hertz;
1010

11+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12+
pub enum MsiFreq {
13+
#[doc = "range 0 around 100 kHz"]
14+
RANGE100K = 0,
15+
#[doc = "range 1 around 200 kHz"]
16+
RANGE200K = 1,
17+
#[doc = "range 2 around 400 kHz"]
18+
RANGE400K = 2,
19+
#[doc = "range 3 around 800 kHz"]
20+
RANGE800K = 3,
21+
#[doc = "range 4 around 1 MHz"]
22+
RANGE1M = 4,
23+
#[doc = "range 5 around 2 MHz"]
24+
RANGE2M = 5,
25+
#[doc = "range 6 around 4 MHz"]
26+
RANGE4M = 6,
27+
#[doc = "range 7 around 8 MHz"]
28+
RANGE8M = 7,
29+
#[doc = "range 8 around 16 MHz"]
30+
RANGE16M = 8,
31+
#[doc = "range 9 around 24 MHz"]
32+
RANGE24M = 9,
33+
#[doc = "range 10 around 32 MHz"]
34+
RANGE32M = 10,
35+
#[doc = "range 11 around 48 MHz"]
36+
RANGE48M = 11,
37+
}
38+
1139
/// Extension trait that constrains the `RCC` peripheral
1240
pub trait RccExt {
1341
/// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
1442
fn constrain(self) -> Rcc;
1543
}
1644

1745
impl RccExt for RCC {
46+
1847
fn constrain(self) -> Rcc {
1948
Rcc {
2049
ahb1: AHB1 { _0: () },
@@ -25,10 +54,13 @@ impl RccExt for RCC {
2554
apb2: APB2 { _0: () },
2655
bdcr: BDCR { _0: () },
2756
csr: CSR { _0: () },
57+
#[cfg(not(feature = "stm32l47x"))]
2858
crrcr: CRRCR { _0: () },
2959
cfgr: CFGR {
3060
hclk: None,
61+
#[cfg(not(feature = "stm32l47x"))]
3162
hsi48: false,
63+
msi: None,
3264
lsi: false,
3365
pclk1: None,
3466
pclk2: None,
@@ -60,6 +92,7 @@ pub struct Rcc {
6092
/// Control/Status Register
6193
pub csr: CSR,
6294
/// Clock recovery RC register
95+
#[cfg(not(feature = "stm32l47x"))]
6396
pub crrcr: CRRCR,
6497
}
6598

@@ -78,17 +111,20 @@ impl CSR {
78111
}
79112

80113
/// Clock recovery RC register
114+
#[cfg(not(feature = "stm32l47x"))]
81115
pub struct CRRCR {
82116
_0: (),
83117
}
84118

119+
#[cfg(not(feature = "stm32l47x"))]
85120
impl CRRCR {
86121
// TODO remove `allow`
87122
#[allow(dead_code)]
88123
pub(crate) fn crrcr(&mut self) -> &rcc::CRRCR {
89124
// NOTE(unsafe) this proxy grants exclusive access to this register
90125
unsafe { &(*RCC::ptr()).crrcr }
91126
}
127+
92128
pub fn is_hsi48_on(&mut self) -> bool {
93129
self.crrcr().read().hsi48on().bit()
94130
}
@@ -228,7 +264,9 @@ const HSI: u32 = 16_000_000; // Hz
228264
pub struct CFGR {
229265
hclk: Option<u32>,
230266
// should we use an option? it can really only be on/off
267+
#[cfg(not(feature = "stm32l47x"))]
231268
hsi48: bool,
269+
msi: Option<MsiFreq>,
232270
lsi: bool,
233271
pclk1: Option<u32>,
234272
pclk2: Option<u32>,
@@ -246,13 +284,20 @@ impl CFGR {
246284
self
247285
}
248286

249-
/// Sets HSI48 clock on or off (the default)
287+
/// Enable the 48Mh USB, RNG, SDMMC clock source.
288+
#[cfg(not(feature = "stm32l47x"))]
250289
pub fn hsi48(mut self, on: bool) -> Self
251290
{
252291
self.hsi48 = on;
253292
self
254293
}
255294

295+
pub fn msi(mut self, range: MsiFreq) -> Self
296+
{
297+
self.msi = Some(range);
298+
self
299+
}
300+
256301
/// Sets LSI clock on (the default) or off
257302
pub fn lsi(mut self, on: bool) -> Self
258303
{
@@ -298,7 +343,7 @@ impl CFGR {
298343
}
299344

300345
/// Freezes the clock configuration, making it effective
301-
pub fn freeze(self, acr: &mut ACR) -> Clocks {
346+
pub fn common_freeze(&self, acr: &mut ACR) -> (Hertz, Hertz, Hertz, u8, u8, Hertz){
302347

303348
let pllconf = if self.pllcfg.is_none() {
304349
let plln = (2 * self.sysclk.unwrap_or(HSI)) / HSI;
@@ -456,27 +501,73 @@ impl CFGR {
456501
while rcc.csr.read().lsirdy().bit_is_clear() {}
457502
}
458503

459-
// Turn on HSI48 if required
460-
if self.hsi48 {
504+
if let Some(msi) = self.msi {
505+
unsafe { rcc.cr.modify(|_, w| w.msirange().bits(msi as u8).msirgsel().set_bit().msion().set_bit() )};
506+
// Wait until MSI is running
507+
while rcc.cr.read().msirdy().bit_is_clear() {}
508+
}
509+
510+
(Hertz(hclk), Hertz(pclk1), Hertz(pclk2), ppre1, ppre2, Hertz(sysclk))
511+
}
512+
513+
514+
#[cfg(not(feature = "stm32l47x"))]
515+
pub fn freeze(self, acr: &mut ACR) -> Clocks {
516+
517+
let (hclk, pclk1, pclk2, ppre1, ppre2, sysclk) = self.common_freeze(acr);
518+
let mut usb_rng = false;
519+
520+
let rcc = unsafe { &*RCC::ptr() };
521+
// Turn on USB, RNG Clock using the HSI48CLK source (default)
522+
if !cfg!(feature = "stm32l47x") && self.hsi48 {
461523
// p. 180 in ref-manual
462524
rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
463525
// Wait until HSI48 is running
464526
while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
527+
usb_rng = true;
465528
}
466529

530+
Clocks {
531+
hclk,
532+
lsi: self.lsi,
533+
hsi48: self.hsi48,
534+
usb_rng,
535+
msi: self.msi,
536+
pclk1,
537+
pclk2,
538+
ppre1,
539+
ppre2,
540+
sysclk,
541+
}
542+
}
543+
544+
#[cfg(feature = "stm32l47x")]
545+
pub fn freeze(self, acr: &mut ACR) -> Clocks {
467546

547+
let (hclk, pclk1, pclk2, ppre1, ppre2, sysclk) = self.common_freeze(acr);
548+
549+
let mut usb_rng = false;
550+
551+
let rcc = unsafe { &*RCC::ptr() };
552+
// Select MSI as clock source for usb48, rng ...
553+
if let Some(MsiFreq::RANGE48M) = self.msi {
554+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b11)) };
555+
usb_rng = true;
556+
}
468557

469558
Clocks {
470-
hclk: Hertz(hclk),
471-
hsi48: self.hsi48,
559+
hclk,
472560
lsi: self.lsi,
473-
pclk1: Hertz(pclk1),
474-
pclk2: Hertz(pclk2),
561+
usb_rng,
562+
msi: self.msi,
563+
pclk1,
564+
pclk2,
475565
ppre1,
476566
ppre2,
477-
sysclk: Hertz(sysclk),
567+
sysclk,
478568
}
479569
}
570+
480571
}
481572

482573
#[derive(Clone, Copy)]
@@ -496,7 +587,10 @@ pub struct PllConfig {
496587
#[derive(Clone, Copy, Debug)]
497588
pub struct Clocks {
498589
hclk: Hertz,
590+
#[cfg(not(feature = "stm32l47x"))]
499591
hsi48: bool,
592+
usb_rng: bool,
593+
msi: Option<MsiFreq>,
500594
lsi: bool,
501595
pclk1: Hertz,
502596
pclk2: Hertz,
@@ -514,10 +608,16 @@ impl Clocks {
514608
}
515609

516610
/// Returns status of HSI48
611+
#[cfg(not(feature = "stm32l47x"))]
517612
pub fn hsi48(&self) -> bool {
518613
self.hsi48
519614
}
520615

616+
/// Returns if usb rng clock is available
617+
pub fn usb_rng(&self) -> bool {
618+
self.usb_rng
619+
}
620+
521621
/// Returns status of HSI48
522622
pub fn lsi(&self) -> bool {
523623
self.lsi

src/rng.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl RngExt for RNG {
2121

2222
// hsi48 should be turned on previously
2323
// TODO: should we return a Result instead of asserting here?
24-
assert!(clocks.hsi48());
24+
assert!(clocks.usb_rng());
2525

2626
ahb2.enr().modify(|_, w| w.rngen().set_bit());
2727
// if we don't do this... we can be "too fast", and

0 commit comments

Comments
 (0)