Skip to content

Commit 91f65b8

Browse files
committed
Use HSI48 and clock recovery system to clock USB
1 parent 8128d53 commit 91f65b8

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

examples/usb_serial.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use hal::rcc::PllMDiv;
1414
use hal::rcc::PllNMul;
1515
use hal::rcc::PllQDiv;
1616
use hal::rcc::PllRDiv;
17+
use hal::usb::configure_usb_clock_source;
18+
use hal::usb::ClockSource;
1719
use panic_probe as _;
1820

1921
use stm32g4 as _;
@@ -32,6 +34,8 @@ pub fn exit() -> ! {
3234

3335
use hal::rcc::{Config, PLLSrc, Prescaler};
3436

37+
use hal::rcc::clock_recovery_system::{CrsConfig, CrsExt};
38+
3539
use stm32g4xx_hal as hal;
3640

3741
use hal::prelude::*;
@@ -43,8 +47,6 @@ use usbd_serial::{SerialPort, USB_CLASS_CDC};
4347

4448
#[cortex_m_rt::entry]
4549
fn main() -> ! {
46-
// utils::logger::init();
47-
4850
let dp = stm32::Peripherals::take().unwrap();
4951

5052
let rcc = dp.RCC.constrain();
@@ -70,12 +72,11 @@ fn main() -> ! {
7072
.apb2_psc(Prescaler::Div2),
7173
);
7274

73-
{
74-
use crate::stm32::RCC;
75-
let rcc = unsafe { &*RCC::ptr() };
76-
// Set clock source for USB to PLL
77-
rcc.ccipr.modify(|_, w| w.clk48sel().pllq());
78-
}
75+
// Example of setting up the HSI48 with the clock recovery system.
76+
let crs = dp.CRS.constrain();
77+
let crs_config = CrsConfig {};
78+
crs.configure(crs_config, &rcc);
79+
configure_usb_clock_source(ClockSource::Hsi48, &rcc);
7980

8081
// Configure an LED
8182
let gpioa = dp.GPIOA.split(&mut rcc);

src/rcc/clock_recovery_system.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::stm32::CRS;
2+
3+
use super::Rcc;
4+
5+
use crate::rcc::Enable;
6+
7+
pub struct CrsConfig {}
8+
9+
pub struct Crs {
10+
rb: CRS,
11+
}
12+
13+
impl Crs {
14+
/// Sets up the clock recovery system for the HSI48 oscillator.
15+
/// TODO: make this configurable for more than just USB applications.
16+
pub fn configure(self, crs_config: CrsConfig, rcc: &Rcc) -> Self {
17+
// TODO: This needs to ensure that the HSI48 is enabled
18+
// and then setup the CRS. For now this just needs to use
19+
// the USB sync as the trigger system.
20+
21+
rcc.enable_hsi48();
22+
23+
// Enable the clock recovery system
24+
CRS::enable(&rcc.rb);
25+
26+
// Set to b10 for USB SOF as source
27+
self.rb
28+
.cfgr
29+
.modify(|_, w| unsafe { w.syncsrc().bits(0b10) });
30+
31+
self.rb.cr.modify(|_, w| {
32+
// Set autotrim enabled.
33+
w.autotrimen().set_bit();
34+
// Enable CRS
35+
w.cen().set_bit()
36+
});
37+
38+
self
39+
}
40+
}
41+
42+
pub trait CrsExt {
43+
/// Constrains the `CRS` peripheral so that it can only be setup once.
44+
fn constrain(self) -> Crs;
45+
}
46+
47+
impl CrsExt for CRS {
48+
fn constrain(self) -> Crs {
49+
Crs { rb: self }
50+
}
51+
}

src/rcc/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::stm32::{rcc, FLASH, PWR, RCC};
22
use crate::time::{Hertz, U32Ext};
33

4+
pub mod clock_recovery_system;
45
mod clockout;
56
mod config;
67
mod enable;
@@ -290,6 +291,16 @@ impl Rcc {
290291
self.rb.csr.modify(|_, w| w.lsion().set_bit());
291292
while self.rb.csr.read().lsirdy().bit_is_clear() {}
292293
}
294+
295+
pub(crate) fn enable_hsi48(&self) {
296+
self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());
297+
298+
loop {
299+
if self.rb.crrcr.read().hsi48rdy().bit() {
300+
break;
301+
}
302+
}
303+
}
293304
}
294305

295306
/// Extension trait that constrains the `RCC` peripheral

src/usb.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use stm32_usbd::UsbPeripheral;
1212

1313
pub use stm32_usbd::UsbBus;
1414

15+
use crate::rcc::Rcc;
16+
1517
pub struct Peripheral {
1618
pub usb: USB,
1719
}
@@ -44,4 +46,17 @@ unsafe impl UsbPeripheral for Peripheral {
4446
}
4547
}
4648

49+
pub enum ClockSource {
50+
Hsi48,
51+
PllQ,
52+
}
53+
54+
#[inline(always)]
55+
pub fn configure_usb_clock_source(cs: ClockSource, rcc: &Rcc) {
56+
rcc.rb.ccipr.modify(|_, w| match cs {
57+
ClockSource::Hsi48 => w.clk48sel().hsi48(),
58+
ClockSource::PllQ => w.clk48sel().pllq(),
59+
});
60+
}
61+
4762
pub type UsbBusType = UsbBus<Peripheral>;

0 commit comments

Comments
 (0)