@@ -100,16 +100,18 @@ const HSI: u32 = 8_000_000; // Hz
100
100
#[ cfg( any( feature = "stm32f301" , feature = "stm32f334" , ) ) ]
101
101
mod usb_clocking {
102
102
use crate :: stm32:: rcc:: cfgr;
103
+ use crate :: rcc:: PllConfig ;
103
104
104
- pub fn is_valid (
105
+ pub ( crate ) fn is_valid (
105
106
_sysclk : & u32 ,
106
107
_hse : & Option < u32 > ,
107
- _pll_options : & Option < ( cfgr:: PLLMUL_A , cfgr:: PLLSRC_A ) > ,
108
+ _pclk1 : & u32 ,
109
+ _pll_config : & Option < PllConfig > ,
108
110
) -> ( bool , bool ) {
109
111
( false , false )
110
112
}
111
113
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 {
113
115
w
114
116
}
115
117
}
@@ -126,24 +128,33 @@ mod usb_clocking {
126
128
) ) ]
127
129
mod usb_clocking {
128
130
use crate :: stm32:: rcc:: cfgr;
131
+ use crate :: rcc:: PllConfig ;
129
132
130
- pub fn is_valid (
133
+ /// Check for all clock options to be
134
+ pub ( crate ) fn is_valid (
131
135
sysclk : & u32 ,
132
136
hse : & Option < u32 > ,
133
- pll_options : & Option < ( cfgr:: PLLMUL_A , cfgr:: PLLSRC_A ) > ,
137
+ pclk1 : & u32 ,
138
+ pll_config : & Option < PllConfig > ,
134
139
) -> ( cfgr:: USBPRE_A , bool ) {
135
140
// the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
136
141
// PLL output frequency is a supported one.
137
142
// 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 )
143
154
}
144
155
}
145
156
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 {
147
158
w. usbpre ( ) . variant ( usb_prescale)
148
159
}
149
160
}
@@ -157,7 +168,7 @@ pub struct CFGR {
157
168
sysclk : Option < u32 > ,
158
169
}
159
170
160
- struct PllConfig {
171
+ pub ( crate ) struct PllConfig {
161
172
src : rcc:: cfgr:: PLLSRC_A ,
162
173
mul : rcc:: cfgr:: PLLMUL_A ,
163
174
div : Option < rcc:: cfgr2:: PREDIV_A > ,
@@ -534,7 +545,7 @@ impl CFGR {
534
545
} )
535
546
}
536
547
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 ) ;
538
549
539
550
let rcc = unsafe { & * RCC :: ptr ( ) } ;
540
551
0 commit comments