Skip to content

Commit

Permalink
Use HSI48 and clock recovery system to clock USB
Browse files Browse the repository at this point in the history
  • Loading branch information
kevswims committed Feb 15, 2023
1 parent 8128d53 commit 91f65b8
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 8 deletions.
17 changes: 9 additions & 8 deletions examples/usb_serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use hal::rcc::PllMDiv;
use hal::rcc::PllNMul;
use hal::rcc::PllQDiv;
use hal::rcc::PllRDiv;
use hal::usb::configure_usb_clock_source;
use hal::usb::ClockSource;
use panic_probe as _;

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

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

use hal::rcc::clock_recovery_system::{CrsConfig, CrsExt};

use stm32g4xx_hal as hal;

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

#[cortex_m_rt::entry]
fn main() -> ! {
// utils::logger::init();

let dp = stm32::Peripherals::take().unwrap();

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

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

// Configure an LED
let gpioa = dp.GPIOA.split(&mut rcc);
Expand Down
51 changes: 51 additions & 0 deletions src/rcc/clock_recovery_system.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::stm32::CRS;

use super::Rcc;

use crate::rcc::Enable;

pub struct CrsConfig {}

pub struct Crs {
rb: CRS,
}

impl Crs {
/// Sets up the clock recovery system for the HSI48 oscillator.
/// TODO: make this configurable for more than just USB applications.
pub fn configure(self, crs_config: CrsConfig, rcc: &Rcc) -> Self {
// TODO: This needs to ensure that the HSI48 is enabled
// and then setup the CRS. For now this just needs to use
// the USB sync as the trigger system.

rcc.enable_hsi48();

// Enable the clock recovery system
CRS::enable(&rcc.rb);

// Set to b10 for USB SOF as source
self.rb
.cfgr
.modify(|_, w| unsafe { w.syncsrc().bits(0b10) });

self.rb.cr.modify(|_, w| {
// Set autotrim enabled.
w.autotrimen().set_bit();
// Enable CRS
w.cen().set_bit()
});

self
}
}

pub trait CrsExt {
/// Constrains the `CRS` peripheral so that it can only be setup once.
fn constrain(self) -> Crs;
}

impl CrsExt for CRS {
fn constrain(self) -> Crs {
Crs { rb: self }
}
}
11 changes: 11 additions & 0 deletions src/rcc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::stm32::{rcc, FLASH, PWR, RCC};
use crate::time::{Hertz, U32Ext};

pub mod clock_recovery_system;
mod clockout;
mod config;
mod enable;
Expand Down Expand Up @@ -290,6 +291,16 @@ impl Rcc {
self.rb.csr.modify(|_, w| w.lsion().set_bit());
while self.rb.csr.read().lsirdy().bit_is_clear() {}
}

pub(crate) fn enable_hsi48(&self) {
self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());

loop {
if self.rb.crrcr.read().hsi48rdy().bit() {
break;
}
}
}
}

/// Extension trait that constrains the `RCC` peripheral
Expand Down
15 changes: 15 additions & 0 deletions src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use stm32_usbd::UsbPeripheral;

pub use stm32_usbd::UsbBus;

use crate::rcc::Rcc;

pub struct Peripheral {
pub usb: USB,
}
Expand Down Expand Up @@ -44,4 +46,17 @@ unsafe impl UsbPeripheral for Peripheral {
}
}

pub enum ClockSource {
Hsi48,
PllQ,
}

#[inline(always)]
pub fn configure_usb_clock_source(cs: ClockSource, rcc: &Rcc) {
rcc.rb.ccipr.modify(|_, w| match cs {
ClockSource::Hsi48 => w.clk48sel().hsi48(),
ClockSource::PllQ => w.clk48sel().pllq(),
});
}

pub type UsbBusType = UsbBus<Peripheral>;

0 comments on commit 91f65b8

Please sign in to comment.