@@ -41,6 +41,50 @@ pub trait SPConfHelper {
4141 fn post_enable_config ( & self , clocks : & Clocks ) -> Result < u32 , ClockError > ;
4242}
4343
44+ /// Copy and paste macro that:
45+ ///
46+ /// * Sets the clocksel mux to `$selvar`
47+ /// * Resets and halts the div, and applies the calculated div4 bits
48+ /// * Releases reset + halt
49+ /// * Waits for the div to stabilize
50+ /// * Returns `Ok($freq / $conf.div.into_divisor())`
51+ ///
52+ /// Assumes:
53+ ///
54+ /// * self is a configuration struct that has a field called `div`, which
55+ /// is a `Div4`
56+ ///
57+ /// usage:
58+ ///
59+ /// ```rust
60+ /// apply_div4!(self, clksel, clkdiv, variant, freq)
61+ /// ```
62+ ///
63+ /// In the future if we make all the clksel+clkdiv pairs into commonly derivedFrom
64+ /// registers, or if we put some kind of simple trait around those regs, we could
65+ /// do this with something other than a macro, but for now, this is harm-reduction
66+ /// to avoid incorrect copy + paste
67+ macro_rules! apply_div4 {
68+ ( $conf: ident, $selreg: ident, $divreg: ident, $selvar: ident, $freq: ident) => { {
69+ // set clksel
70+ $selreg. modify( |_r, w| w. mux( ) . variant( $selvar) ) ;
71+
72+ // Set up clkdiv
73+ $divreg. modify( |_r, w| {
74+ unsafe { w. div( ) . bits( $conf. div. into_bits( ) ) }
75+ . halt( )
76+ . asserted( )
77+ . reset( )
78+ . asserted( )
79+ } ) ;
80+ $divreg. modify( |_r, w| w. halt( ) . deasserted( ) . reset( ) . deasserted( ) ) ;
81+
82+ while $divreg. read( ) . unstab( ) . is_unstable( ) { }
83+
84+ Ok ( $freq / $conf. div. into_divisor( ) )
85+ } } ;
86+ }
87+
4488// config types
4589
4690/// This type represents a divider in the range 1..=16.
@@ -217,22 +261,7 @@ impl SPConfHelper for Lpi2cConfig {
217261 } ,
218262 } ;
219263
220- // set clksel
221- clksel. modify ( |_r, w| w. mux ( ) . variant ( variant) ) ;
222-
223- // Set up clkdiv
224- clkdiv. modify ( |_r, w| {
225- unsafe { w. div ( ) . bits ( self . div . into_bits ( ) ) }
226- . halt ( )
227- . asserted ( )
228- . reset ( )
229- . asserted ( )
230- } ) ;
231- clkdiv. modify ( |_r, w| w. halt ( ) . deasserted ( ) . reset ( ) . deasserted ( ) ) ;
232-
233- while clkdiv. read ( ) . unstab ( ) . is_unstable ( ) { }
234-
235- Ok ( freq / self . div . into_divisor ( ) )
264+ apply_div4 ! ( self , clksel, clkdiv, variant, freq)
236265 }
237266}
238267
@@ -347,24 +376,7 @@ impl SPConfHelper for LpuartConfig {
347376 } ;
348377
349378 // set clksel
350- clksel. modify ( |_r, w| w. mux ( ) . variant ( variant) ) ;
351-
352- // Set up clkdiv
353- clkdiv. modify ( |_r, w| {
354- w. halt ( ) . asserted ( ) ;
355- w. reset ( ) . asserted ( ) ;
356- unsafe { w. div ( ) . bits ( self . div . into_bits ( ) ) } ;
357- w
358- } ) ;
359- clkdiv. modify ( |_r, w| {
360- w. halt ( ) . deasserted ( ) ;
361- w. reset ( ) . deasserted ( ) ;
362- w
363- } ) ;
364-
365- while clkdiv. read ( ) . unstab ( ) . is_unstable ( ) { }
366-
367- Ok ( freq / self . div . into_divisor ( ) )
379+ apply_div4 ! ( self , clksel, clkdiv, variant, freq)
368380 }
369381}
370382
@@ -482,25 +494,9 @@ impl SPConfHelper for AdcConfig {
482494 return Ok ( 0 ) ;
483495 }
484496 } ;
497+ let clksel = mrcc0. mrcc_adc_clksel ( ) ;
498+ let clkdiv = mrcc0. mrcc_adc_clkdiv ( ) ;
485499
486- // set clksel
487- mrcc0. mrcc_adc_clksel ( ) . modify ( |_r, w| w. mux ( ) . variant ( variant) ) ;
488-
489- // Set up clkdiv
490- mrcc0. mrcc_adc_clkdiv ( ) . modify ( |_r, w| {
491- w. halt ( ) . asserted ( ) ;
492- w. reset ( ) . asserted ( ) ;
493- unsafe { w. div ( ) . bits ( self . div . into_bits ( ) ) } ;
494- w
495- } ) ;
496- mrcc0. mrcc_adc_clkdiv ( ) . modify ( |_r, w| {
497- w. halt ( ) . deasserted ( ) ;
498- w. reset ( ) . deasserted ( ) ;
499- w
500- } ) ;
501-
502- while mrcc0. mrcc_adc_clkdiv ( ) . read ( ) . unstab ( ) . is_unstable ( ) { }
503-
504- Ok ( freq / self . div . into_divisor ( ) )
500+ apply_div4 ! ( self , clksel, clkdiv, variant, freq)
505501 }
506502}
0 commit comments