mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-28 04:40:39 +00:00
Working USB_OTG_HS example
This commit is contained in:
parent
0545353ec1
commit
1d3c48cf45
@ -1599,7 +1599,7 @@ fn main() {
|
|||||||
for e in rcc_registers.ir.enums {
|
for e in rcc_registers.ir.enums {
|
||||||
fn is_rcc_name(e: &str) -> bool {
|
fn is_rcc_name(e: &str) -> bool {
|
||||||
match e {
|
match e {
|
||||||
"Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true,
|
"Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true,
|
||||||
"Timpre" | "Pllrclkpre" => false,
|
"Timpre" | "Pllrclkpre" => false,
|
||||||
e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
|
e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1,43 +1,23 @@
|
|||||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
||||||
use crate::pac::rcc::regs::Cfgr1;
|
use crate::pac::rcc::regs::Cfgr1;
|
||||||
use core::ops::Div;
|
#[cfg(all(peri_usb_otg_hs))]
|
||||||
pub use crate::pac::rcc::vals::{
|
pub use crate::pac::rcc::vals::Otghssel;
|
||||||
Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource,
|
|
||||||
Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Hpre5 as AHB5Prescaler, Hdiv5,
|
|
||||||
};
|
|
||||||
use crate::pac::rcc::vals::Pllrge;
|
use crate::pac::rcc::vals::Pllrge;
|
||||||
|
pub use crate::pac::rcc::vals::{
|
||||||
|
Hdiv5, Hpre as AHBPrescaler, Hpre5 as AHB5Prescaler, Hsepre as HsePrescaler, Plldiv as PllDiv, Pllm as PllPreDiv,
|
||||||
|
Plln as PllMul, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk,
|
||||||
|
};
|
||||||
|
#[cfg(all(peri_usb_otg_hs))]
|
||||||
|
pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG};
|
||||||
use crate::pac::{FLASH, RCC};
|
use crate::pac::{FLASH, RCC};
|
||||||
use crate::rcc::LSI_FREQ;
|
use crate::rcc::LSI_FREQ;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
#[cfg(all(peri_usb_otg_hs))]
|
|
||||||
pub use crate::pac::rcc::vals::Otghssel;
|
|
||||||
|
|
||||||
#[cfg(all(peri_usb_otg_hs))]
|
|
||||||
pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG};
|
|
||||||
|
|
||||||
/// HSI speed
|
/// HSI speed
|
||||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
||||||
// HSE speed
|
// HSE speed
|
||||||
pub const HSE_FREQ: Hertz = Hertz(32_000_000);
|
pub const HSE_FREQ: Hertz = Hertz(32_000_000);
|
||||||
|
|
||||||
// Allow dividing a Hertz value by an AHB5 prescaler directly
|
|
||||||
impl Div<AHB5Prescaler> for Hertz {
|
|
||||||
type Output = Hertz;
|
|
||||||
fn div(self, rhs: AHB5Prescaler) -> Hertz {
|
|
||||||
// Map the prescaler enum to its integer divisor
|
|
||||||
let divisor = match rhs {
|
|
||||||
AHB5Prescaler::DIV1 => 1,
|
|
||||||
AHB5Prescaler::DIV2 => 2,
|
|
||||||
AHB5Prescaler::DIV3 => 3,
|
|
||||||
AHB5Prescaler::DIV4 => 4,
|
|
||||||
AHB5Prescaler::DIV6 => 6,
|
|
||||||
_ => unreachable!("Invalid AHB5 prescaler: {:?}", rhs),
|
|
||||||
};
|
|
||||||
Hertz(self.0 / divisor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct Hse {
|
pub struct Hse {
|
||||||
pub prescaler: HsePrescaler,
|
pub prescaler: HsePrescaler,
|
||||||
@ -95,8 +75,7 @@ pub struct Config {
|
|||||||
pub apb7_pre: APBPrescaler,
|
pub apb7_pre: APBPrescaler,
|
||||||
|
|
||||||
// low speed LSI/LSE/RTC
|
// low speed LSI/LSE/RTC
|
||||||
pub lsi: super::LsConfig,
|
pub ls: super::LsConfig,
|
||||||
// pub lsi2: super::LsConfig,
|
|
||||||
|
|
||||||
pub voltage_scale: VoltageScale,
|
pub voltage_scale: VoltageScale,
|
||||||
|
|
||||||
@ -116,7 +95,7 @@ impl Config {
|
|||||||
apb1_pre: APBPrescaler::DIV1,
|
apb1_pre: APBPrescaler::DIV1,
|
||||||
apb2_pre: APBPrescaler::DIV1,
|
apb2_pre: APBPrescaler::DIV1,
|
||||||
apb7_pre: APBPrescaler::DIV1,
|
apb7_pre: APBPrescaler::DIV1,
|
||||||
lsi: crate::rcc::LsConfig::new(),
|
ls: crate::rcc::LsConfig::new(),
|
||||||
// lsi2: crate::rcc::LsConfig::new(),
|
// lsi2: crate::rcc::LsConfig::new(),
|
||||||
voltage_scale: VoltageScale::RANGE2,
|
voltage_scale: VoltageScale::RANGE2,
|
||||||
mux: super::mux::ClockMux::default(),
|
mux: super::mux::ClockMux::default(),
|
||||||
@ -151,7 +130,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale));
|
crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale));
|
||||||
while !crate::pac::PWR.vosr().read().vosrdy() {}
|
while !crate::pac::PWR.vosr().read().vosrdy() {}
|
||||||
|
|
||||||
let rtc = config.lsi.init();
|
let rtc = config.ls.init();
|
||||||
|
|
||||||
let hsi = config.hsi.then(|| {
|
let hsi = config.hsi.then(|| {
|
||||||
hsi_enable();
|
hsi_enable();
|
||||||
@ -169,7 +148,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
HSE_FREQ
|
HSE_FREQ
|
||||||
});
|
});
|
||||||
|
|
||||||
let pll_input = PllInput {hse, hsi };
|
let pll_input = PllInput { hse, hsi };
|
||||||
|
|
||||||
let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale);
|
let pll1 = init_pll(config.pll1, &pll_input, config.voltage_scale);
|
||||||
|
|
||||||
@ -250,7 +229,6 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
|
|
||||||
let hclk5 = sys_clk / config.ahb5_pre;
|
let hclk5 = sys_clk / config.ahb5_pre;
|
||||||
|
|
||||||
|
|
||||||
#[cfg(all(stm32wba, peri_usb_otg_hs))]
|
#[cfg(all(stm32wba, peri_usb_otg_hs))]
|
||||||
let usb_refck = match config.mux.otghssel {
|
let usb_refck = match config.mux.otghssel {
|
||||||
Otghssel::HSE => hse,
|
Otghssel::HSE => hse,
|
||||||
@ -276,7 +254,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
w.set_clksel(usb_refck_sel);
|
w.set_clksel(usb_refck_sel);
|
||||||
});
|
});
|
||||||
|
|
||||||
let lsi = config.lsi.lsi.then_some(LSI_FREQ);
|
let lsi = config.ls.lsi.then_some(LSI_FREQ);
|
||||||
|
|
||||||
config.mux.init();
|
config.mux.init();
|
||||||
|
|
||||||
@ -360,7 +338,7 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale)
|
|||||||
// let vco_freq = ref_freq * pll.mul;
|
// let vco_freq = ref_freq * pll.mul;
|
||||||
// Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13)
|
// Calculate VCO frequency including fractional part: FVCO = Fref_ck × (N + FRAC/2^13)
|
||||||
let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64);
|
let numerator = (ref_freq.0 as u64) * (((pll.mul as u64) + 1 << 13) + pll.frac.unwrap_or(0) as u64);
|
||||||
let vco_hz = (numerator >> 13) as u32;
|
let vco_hz = (numerator >> 13) as u32;
|
||||||
let vco_freq = Hertz(vco_hz);
|
let vco_freq = Hertz(vco_hz);
|
||||||
assert!(vco_freq >= vco_min && vco_freq <= vco_max);
|
assert!(vco_freq >= vco_min && vco_freq <= vco_max);
|
||||||
|
|
||||||
@ -381,7 +359,9 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale)
|
|||||||
w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1));
|
w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1));
|
||||||
w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1));
|
w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1));
|
||||||
});
|
});
|
||||||
RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(0));});
|
RCC.pll1fracr().write(|w| {
|
||||||
|
w.set_pllfracn(pll.frac.unwrap_or(0));
|
||||||
|
});
|
||||||
|
|
||||||
let input_range = match ref_freq.0 {
|
let input_range = match ref_freq.0 {
|
||||||
..=8_000_000 => Pllrge::FREQ_4TO8MHZ,
|
..=8_000_000 => Pllrge::FREQ_4TO8MHZ,
|
||||||
@ -400,10 +380,12 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
RCC.pll1cfgr().write(|w| {write_fields!(w);});
|
RCC.pll1cfgr().write(|w| {
|
||||||
|
write_fields!(w);
|
||||||
|
});
|
||||||
|
|
||||||
// Enable PLL
|
// Enable PLL
|
||||||
pll_enable(true);
|
pll_enable(true);
|
||||||
|
|
||||||
PllOutput{ p, q, r }
|
PllOutput { p, q, r }
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ fn common_init<T: Instance>() {
|
|||||||
w.set_usv(crate::pac::pwr::vals::Usv::B_0X1);
|
w.set_usv(crate::pac::pwr::vals::Usv::B_0X1);
|
||||||
});
|
});
|
||||||
crate::pac::PWR.vosr().modify(|w| {
|
crate::pac::PWR.vosr().modify(|w| {
|
||||||
w.set_vdd11usbdis(true);
|
w.set_vdd11usbdis(false);
|
||||||
});
|
});
|
||||||
crate::pac::PWR.vosr().modify(|w| {
|
crate::pac::PWR.vosr().modify(|w| {
|
||||||
w.set_usbpwren(true);
|
w.set_usbpwren(true);
|
||||||
|
@ -9,7 +9,6 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [
|
|||||||
embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.7.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
|
embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
|
||||||
embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true }
|
|
||||||
embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ defmt-rtt = "1.0.0"
|
|||||||
|
|
||||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||||
cortex-m-rt = "0.7.0"
|
cortex-m-rt = "0.7.0"
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "0.2.6"
|
||||||
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
||||||
heapless = { version = "0.8", default-features = false }
|
heapless = { version = "0.8", default-features = false }
|
||||||
static_cell = "2"
|
static_cell = "2"
|
||||||
|
@ -2,17 +2,14 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use defmt_rtt as _; // global logger
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::rcc::{mux, AHB5Prescaler, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale};
|
|
||||||
use embassy_stm32::rcc::{PllDiv, PllMul, PllPreDiv, PllSource};
|
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use panic_probe as _;
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
|
USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
|
||||||
@ -24,37 +21,44 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
|
|
||||||
// External HSE (32 MHz) setup
|
|
||||||
// config.rcc.hse = Some(Hse {
|
|
||||||
// prescaler: HsePrescaler::DIV2,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Fine-tune PLL1 dividers/multipliers
|
{
|
||||||
config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
|
use embassy_stm32::rcc::*;
|
||||||
source: PllSource::HSI,
|
// External HSE (32 MHz) setup
|
||||||
prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
|
// config.rcc.hse = Some(Hse {
|
||||||
mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
|
// prescaler: HsePrescaler::DIV2,
|
||||||
divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
|
// });
|
||||||
// divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
|
|
||||||
divq: None,
|
|
||||||
divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
|
|
||||||
frac: Some(0), // Fractional part (enabled)
|
|
||||||
});
|
|
||||||
|
|
||||||
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
// Fine-tune PLL1 dividers/multipliers
|
||||||
config.rcc.apb1_pre = APBPrescaler::DIV1;
|
config.rcc.pll1 = Some(Pll {
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
source: PllSource::HSI,
|
||||||
config.rcc.apb7_pre = APBPrescaler::DIV1;
|
prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
|
||||||
config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
|
mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
|
||||||
|
divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
|
||||||
|
divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
|
||||||
|
// divq: None,
|
||||||
|
divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
|
||||||
|
frac: Some(0), // Fractional part (enabled)
|
||||||
|
});
|
||||||
|
|
||||||
// voltage scale for max performance
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
config.rcc.voltage_scale = VoltageScale::RANGE1;
|
config.rcc.apb1_pre = APBPrescaler::DIV1;
|
||||||
// route PLL1_P into the USB‐OTG‐HS block
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
config.rcc.mux.otghssel = mux::Otghssel::PLL1_P;
|
config.rcc.apb7_pre = APBPrescaler::DIV1;
|
||||||
config.rcc.sys = Sysclk::PLL1_R;
|
config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
|
||||||
|
|
||||||
|
config.rcc.voltage_scale = VoltageScale::RANGE1;
|
||||||
|
config.rcc.mux.otghssel = mux::Otghssel::PLL1_P;
|
||||||
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
|
}
|
||||||
|
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
|
// TRDT set to 5
|
||||||
|
// ASVLD set to 1
|
||||||
|
// BSVLD set to 1
|
||||||
|
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user