Skip to content

Commit 920778a

Browse files
committed
Implement LPUART1 clock source changing.
1 parent ef432ab commit 920778a

File tree

4 files changed

+155
-3
lines changed

4 files changed

+155
-3
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,7 @@ required-features = ["rt"]
203203
[[example]]
204204
name = "adc_dma"
205205
required-features = ["rt"]
206+
207+
[[example]]
208+
name = "serial_lpuart1_rtic"
209+
required-features = ["rt", "stm32l476"]

examples/serial_lpuart1_rtic.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
extern crate panic_rtt_target;
5+
6+
use heapless::{consts::U8, spsc};
7+
use nb::block;
8+
use rtt_target::{rprint, rprintln};
9+
use stm32l4xx_hal::{
10+
pac::{self, LPUART1},
11+
prelude::*,
12+
serial::{self, Config, Serial},
13+
};
14+
15+
#[rtic::app(device = stm32l4xx_hal::pac)]
16+
const APP: () = {
17+
struct Resources {
18+
rx: serial::Rx<LPUART1>,
19+
tx: serial::Tx<LPUART1>,
20+
//
21+
// rx_prod: spsc::Producer<'static, u8, U8>,
22+
// rx_cons: spsc::Consumer<'static, u8, U8>,
23+
}
24+
25+
#[init]
26+
fn init(_: init::Context) -> init::LateResources {
27+
static mut RX_QUEUE: spsc::Queue<u8, U8> = spsc::Queue(heapless::i::Queue::new());
28+
29+
rtt_target::rtt_init_print!();
30+
rprint!("Initializing... ");
31+
32+
let p = pac::Peripherals::take().unwrap();
33+
34+
let mut rcc = p.RCC.constrain();
35+
let mut flash = p.FLASH.constrain();
36+
let mut pwr = p.PWR.constrain(&mut rcc.apb1r1);
37+
38+
let clocks = rcc.cfgr.freeze(&mut flash.acr, &mut pwr);
39+
40+
let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
41+
let mut gpioc = p.GPIOC.split(&mut rcc.ahb2);
42+
43+
let tx_pin = gpioc
44+
.pc1
45+
.into_alternate(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrl);
46+
let rx_pin = gpioc
47+
.pc0
48+
.into_alternate(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrl);
49+
50+
let mut serial = Serial::lpuart1(
51+
p.LPUART1,
52+
(tx_pin, rx_pin),
53+
Config::default().baudrate(115_200.bps()),
54+
clocks,
55+
&mut rcc.apb1r2,
56+
);
57+
serial.listen(serial::Event::Rxne);
58+
59+
let (tx, rx) = serial.split();
60+
let (rx_prod, rx_cons) = RX_QUEUE.split();
61+
62+
rprintln!("done.");
63+
64+
init::LateResources {
65+
rx,
66+
tx,
67+
//
68+
// rx_prod,
69+
// rx_cons,
70+
}
71+
}
72+
73+
#[idle(resources = [tx])]
74+
fn idle(cx: idle::Context) -> ! {
75+
// let rx = cx.resources.rx_cons;
76+
let tx = cx.resources.tx;
77+
78+
loop {
79+
// if let Some(b) = rx.dequeue() {
80+
// rprintln!("Echoing '{}'", b as char);
81+
// block!(tx.write(b)).unwrap();
82+
// }
83+
block!(tx.write('x' as u8)).unwrap();
84+
cortex_m::asm::delay(1_000_000);
85+
}
86+
}
87+
88+
#[task(binds = LPUART1, resources = [rx])]
89+
fn usart2(cx: usart2::Context) {
90+
let rx = cx.resources.rx;
91+
// let queue = cx.resources.rx_prod;
92+
93+
let b = match rx.read() {
94+
Ok(b) => {
95+
rprintln!("Read: {}", b);
96+
},
97+
Err(err) => {
98+
rprintln!("Error reading from USART: {:?}", err);
99+
return;
100+
}
101+
};
102+
// match queue.enqueue(b) {
103+
// Ok(()) => (),
104+
// Err(err) => {
105+
// rprintln!("Error adding received byte to queue: {:?}", err);
106+
// return;
107+
// }
108+
// }
109+
}
110+
};

src/rcc.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ impl RccExt for RCC {
8989
sysclk: None,
9090
pll_source: None,
9191
pll_config: None,
92+
lpuart1_src: LpUart1ClockSource::Pclk,
9293
},
9394
}
9495
}
@@ -158,6 +159,14 @@ impl CRRCR {
158159
}
159160
}
160161

162+
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
163+
pub enum LpUart1ClockSource {
164+
Pclk = 0b00,
165+
Sysclk = 0b01,
166+
Hsi16 = 0b10,
167+
Lsi = 0b11
168+
}
169+
161170
/// Peripherals independent clock configuration register
162171
pub struct CCIPR {
163172
_0: (),
@@ -355,6 +364,7 @@ pub struct CFGR {
355364
sysclk: Option<u32>,
356365
pll_source: Option<PllSource>,
357366
pll_config: Option<PllConfig>,
367+
lpuart1_src: LpUart1ClockSource,
358368
}
359369

360370
impl CFGR {
@@ -431,6 +441,12 @@ impl CFGR {
431441
self
432442
}
433443

444+
/// Sets LPUART1 clock source
445+
pub fn lpuart1_clk_src(mut self, source: LpUart1ClockSource) -> Self {
446+
self.lpuart1_src = source;
447+
self
448+
}
449+
434450
/// Freezes the clock configuration, making it effective
435451
pub fn freeze(&self, acr: &mut ACR, pwr: &mut Pwr) -> Clocks {
436452
let rcc = unsafe { &*RCC::ptr() };
@@ -608,8 +624,18 @@ impl CFGR {
608624
};
609625

610626
// Check if HSI should be started
611-
if pll_source == PllSource::HSI16 || (self.msi.is_none() && self.hse.is_none()) {
612-
rcc.cr.write(|w| w.hsion().set_bit());
627+
let lpuart1_clk_from_hsi = match self.lpuart1_src {
628+
LpUart1ClockSource::Hsi16 => {
629+
rcc.ccipr.modify(|_, w| unsafe { w.lpuart1sel().bits(self.lpuart1_src as u8) });
630+
true
631+
}
632+
LpUart1ClockSource::Lsi => {
633+
todo!()
634+
}
635+
_ => false,
636+
};
637+
if pll_source == PllSource::HSI16 || (self.msi.is_none() && self.hse.is_none()) || lpuart1_clk_from_hsi {
638+
rcc.cr.modify(|_, w| w.hsion().set_bit());
613639
while rcc.cr.read().hsirdy().bit_is_clear() {}
614640
}
615641

@@ -819,6 +845,7 @@ impl CFGR {
819845
timclk1: timclk1.Hz(),
820846
timclk2: timclk2.Hz(),
821847
pll_source: pllconf.map(|_| pll_source),
848+
lpuart1_src: self.lpuart1_src
822849
}
823850
}
824851
}
@@ -918,6 +945,7 @@ pub struct Clocks {
918945
timclk1: Hertz,
919946
timclk2: Hertz,
920947
pll_source: Option<PllSource>,
948+
lpuart1_src: LpUart1ClockSource,
921949
}
922950

923951
impl Clocks {
@@ -986,4 +1014,8 @@ impl Clocks {
9861014
pub fn timclk2(&self) -> Hertz {
9871015
self.timclk2
9881016
}
1017+
1018+
pub fn lpuart1_src(&self) -> LpUart1ClockSource {
1019+
self.lpuart1_src
1020+
}
9891021
}

src/serial.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,13 @@ macro_rules! hal {
298298
}
299299
},
300300
{
301-
let fck = clocks.$pclkX().raw();
301+
use crate::rcc::LpUart1ClockSource;
302+
let fck = match clocks.lpuart1_src() {
303+
LpUart1ClockSource::Pclk => clocks.$pclkX().raw(),
304+
LpUart1ClockSource::Sysclk => clocks.sysclk().raw(),
305+
LpUart1ClockSource::Hsi16 => 16_000_000,
306+
LpUart1ClockSource::Lsi => 32_768,
307+
};
302308
assert!((fck >= 3 * config.baudrate.0) && (fck <= 4096 * config.baudrate.0), "impossible baud rate");
303309
let brr = 256u64 * (fck as u64) / config.baudrate.0 as u64;
304310
let brr = brr as u32;

0 commit comments

Comments
 (0)