Skip to content

Commit db2361e

Browse files
committed
Using pllconfig for usb functions and check apb1 frequency
1 parent 0327184 commit db2361e

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

src/rcc.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,18 @@ const HSI: u32 = 8_000_000; // Hz
100100
#[cfg(any(feature = "stm32f301", feature = "stm32f334",))]
101101
mod usb_clocking {
102102
use crate::stm32::rcc::cfgr;
103+
use crate::rcc::PllConfig;
103104

104-
pub fn is_valid(
105+
pub(crate) fn is_valid(
105106
_sysclk: &u32,
106107
_hse: &Option<u32>,
107-
_pll_options: &Option<(cfgr::PLLMUL_A, cfgr::PLLSRC_A)>,
108+
_pclk1: &u32,
109+
_pll_config: &Option<PllConfig>,
108110
) -> (bool, bool) {
109111
(false, false)
110112
}
111113

112-
pub fn set_usbpre<W>(w: &mut W, _: bool) -> &mut W {
114+
pub(crate) fn set_usbpre<W>(w: &mut W, _: bool) -> &mut W {
113115
w
114116
}
115117
}
@@ -126,24 +128,33 @@ mod usb_clocking {
126128
))]
127129
mod usb_clocking {
128130
use crate::stm32::rcc::cfgr;
131+
use crate::rcc::PllConfig;
129132

130-
pub fn is_valid(
133+
/// Check for all clock options to be
134+
pub(crate) fn is_valid(
131135
sysclk: &u32,
132136
hse: &Option<u32>,
133-
pll_options: &Option<(cfgr::PLLMUL_A, cfgr::PLLSRC_A)>,
137+
pclk1: &u32,
138+
pll_config: &Option<PllConfig>,
134139
) -> (cfgr::USBPRE_A, bool) {
135140
// the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
136141
// PLL output frequency is a supported one.
137142
// usbpre == false: divide clock by 1.5, otherwise no division
138-
let usb_ok = hse.is_some() && pll_options.is_some();
139-
match (usb_ok, sysclk) {
140-
(true, 72_000_000) => (cfgr::USBPRE_A::DIV1_5, true),
141-
(true, 48_000_000) => (cfgr::USBPRE_A::DIV1, true),
142-
_ => (cfgr::USBPRE_A::DIV1, false),
143+
let usb_ok = hse.is_some() && pll_config.is_some();
144+
// The APB1 clock must have a minimum frequency of 10 MHz to avoid data overrun/underrun
145+
// problems. [RM0316 32.5.2]
146+
if *pclk1 >= 10_000_000 {
147+
match (usb_ok, sysclk) {
148+
(true, 72_000_000) => (cfgr::USBPRE_A::DIV1_5, true),
149+
(true, 48_000_000) => (cfgr::USBPRE_A::DIV1, true),
150+
_ => (cfgr::USBPRE_A::DIV1, false),
151+
}
152+
} else {
153+
(cfgr::USBPRE_A::DIV1, false)
143154
}
144155
}
145156

146-
pub fn set_usbpre(w: &mut cfgr::W, usb_prescale: cfgr::USBPRE_A) -> &mut cfgr::W {
157+
pub(crate) fn set_usbpre(w: &mut cfgr::W, usb_prescale: cfgr::USBPRE_A) -> &mut cfgr::W {
147158
w.usbpre().variant(usb_prescale)
148159
}
149160
}
@@ -157,7 +168,7 @@ pub struct CFGR {
157168
sysclk: Option<u32>,
158169
}
159170

160-
struct PllConfig {
171+
pub(crate) struct PllConfig {
161172
src: rcc::cfgr::PLLSRC_A,
162173
mul: rcc::cfgr::PLLMUL_A,
163174
div: Option<rcc::cfgr2::PREDIV_A>,
@@ -534,7 +545,7 @@ impl CFGR {
534545
})
535546
}
536547

537-
let (usbpre, usbclk_valid) = usb_clocking::is_valid(&sysclk, &self.hse, &pll_options);
548+
let (usbpre, usbclk_valid) = usb_clocking::is_valid(&sysclk, &self.hse, &pclk1, &pll_config);
538549

539550
let rcc = unsafe { &*RCC::ptr() };
540551

0 commit comments

Comments
 (0)