@@ -145,6 +145,10 @@ pub trait RegisterBlockImpl: crate::Sealed {
145145
146146 // PeriAddress
147147 fn peri_address ( & self ) -> u32 ;
148+
149+ fn enable_dma ( & self , dc : config:: DmaConfig ) ;
150+
151+ fn calculate_brr ( pclk_freq : u32 , baud : u32 ) -> Result < ( bool , u32 ) , config:: InvalidConfig > ;
148152}
149153
150154macro_rules! uartCommon {
@@ -259,6 +263,67 @@ macro_rules! uartCommon {
259263 fn peri_address( & self ) -> u32 {
260264 self . dr( ) . as_ptr( ) as u32
261265 }
266+
267+ fn enable_dma( & self , dc: config:: DmaConfig ) {
268+ use config:: DmaConfig ;
269+ match dc {
270+ DmaConfig :: Tx => self . cr3( ) . write( |w| w. dmat( ) . enabled( ) ) ,
271+ DmaConfig :: Rx => self . cr3( ) . write( |w| w. dmar( ) . enabled( ) ) ,
272+ DmaConfig :: TxRx => self . cr3( ) . write( |w| w. dmar( ) . enabled( ) . dmat( ) . enabled( ) ) ,
273+ DmaConfig :: None => { }
274+ }
275+ }
276+
277+ fn calculate_brr( pclk_freq: u32 , baud: u32 ) -> Result <( bool , u32 ) , config:: InvalidConfig > {
278+ // The frequency to calculate USARTDIV is this:
279+ //
280+ // (Taken from STM32F411xC/E Reference Manual,
281+ // Section 19.3.4, Equation 1)
282+ //
283+ // 16 bit oversample: OVER8 = 0
284+ // 8 bit oversample: OVER8 = 1
285+ //
286+ // USARTDIV = (pclk)
287+ // ------------------------
288+ // 8 x (2 - OVER8) x (baud)
289+ //
290+ // BUT, the USARTDIV has 4 "fractional" bits, which effectively
291+ // means that we need to "correct" the equation as follows:
292+ //
293+ // USARTDIV = (pclk) * 16
294+ // ------------------------
295+ // 8 x (2 - OVER8) x (baud)
296+ //
297+ // When OVER8 is enabled, we can only use the lowest three
298+ // fractional bits, so we'll need to shift those last four bits
299+ // right one bit
300+
301+ // Calculate correct baudrate divisor on the fly
302+ if ( pclk_freq / 16 ) >= baud {
303+ // We have the ability to oversample to 16 bits, take
304+ // advantage of it.
305+ //
306+ // We also add `baud / 2` to the `pclk_freq` to ensure
307+ // rounding of values to the closest scale, rather than the
308+ // floored behavior of normal integer division.
309+ let div = ( pclk_freq + ( baud / 2 ) ) / baud;
310+ Ok ( ( false , div) )
311+ } else if ( pclk_freq / 8 ) >= baud {
312+ // We are close enough to pclk where we can only
313+ // oversample 8.
314+ //
315+ // See note above regarding `baud` and rounding.
316+ let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
317+
318+ // Ensure the the fractional bits (only 3) are
319+ // right-aligned.
320+ let frac = div & 0xF ;
321+ let div = ( div & !0xF ) | ( frac >> 1 ) ;
322+ Ok ( ( true , div) )
323+ } else {
324+ Err ( config:: InvalidConfig )
325+ }
326+ }
262327 } ;
263328}
264329
@@ -282,66 +347,11 @@ where {
282347 let pclk_freq = UART :: clock ( clocks) . raw ( ) ;
283348 let baud = config. baudrate . 0 ;
284349
285- // The frequency to calculate USARTDIV is this:
286- //
287- // (Taken from STM32F411xC/E Reference Manual,
288- // Section 19.3.4, Equation 1)
289- //
290- // 16 bit oversample: OVER8 = 0
291- // 8 bit oversample: OVER8 = 1
292- //
293- // USARTDIV = (pclk)
294- // ------------------------
295- // 8 x (2 - OVER8) x (baud)
296- //
297- // BUT, the USARTDIV has 4 "fractional" bits, which effectively
298- // means that we need to "correct" the equation as follows:
299- //
300- // USARTDIV = (pclk) * 16
301- // ------------------------
302- // 8 x (2 - OVER8) x (baud)
303- //
304- // When OVER8 is enabled, we can only use the lowest three
305- // fractional bits, so we'll need to shift those last four bits
306- // right one bit
307- //
308- // In IrDA Smartcard, LIN, and IrDA modes, OVER8 is always disabled.
309- //
310- // (Taken from STM32F411xC/E Reference Manual,
311- // Section 19.3.4, Equation 2)
312- //
313- // USARTDIV = pclk
314- // ---------
315- // 16 x baud
316- //
317- // With reference to the above, OVER8 == 0 when in Smartcard, LIN, and
318- // IrDA modes, so the register value needed for USARTDIV is the same
319- // as for 16 bit oversampling.
320-
321- // Calculate correct baudrate divisor on the fly
322- let ( over8, div) = if ( pclk_freq / 16 ) >= baud || config. irda != IrdaMode :: None {
323- // We have the ability to oversample to 16 bits, take
324- // advantage of it.
325- //
326- // We also add `baud / 2` to the `pclk_freq` to ensure
327- // rounding of values to the closest scale, rather than the
328- // floored behavior of normal integer division.
350+ let ( over8, div) = if config. irda != IrdaMode :: None {
329351 let div = ( pclk_freq + ( baud / 2 ) ) / baud;
330352 ( false , div)
331- } else if ( pclk_freq / 8 ) >= baud {
332- // We are close enough to pclk where we can only
333- // oversample 8.
334- //
335- // See note above regarding `baud` and rounding.
336- let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
337-
338- // Ensure the the fractional bits (only 3) are
339- // right-aligned.
340- let frac = div & 0xF ;
341- let div = ( div & !0xF ) | ( frac >> 1 ) ;
342- ( true , div)
343353 } else {
344- return Err ( config :: InvalidConfig ) ;
354+ Self :: calculate_brr ( pclk_freq , baud ) ?
345355 } ;
346356
347357 uart. brr ( ) . write ( |w| unsafe { w. bits ( div) } ) ;
@@ -384,12 +394,7 @@ where {
384394 w. ps ( ) . bit ( config. parity == Parity :: ParityOdd )
385395 } ) ;
386396
387- match config. dma {
388- DmaConfig :: Tx => uart. cr3 ( ) . write ( |w| w. dmat ( ) . enabled ( ) ) ,
389- DmaConfig :: Rx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) ) ,
390- DmaConfig :: TxRx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) . dmat ( ) . enabled ( ) ) ,
391- DmaConfig :: None => { }
392- }
397+ uart. enable_dma ( config. dma ) ;
393398
394399 let serial = Serial {
395400 tx : Tx :: new ( uart, pins. 0 . into ( ) ) ,
@@ -423,54 +428,7 @@ where {
423428 let pclk_freq = UART :: clock ( clocks) . raw ( ) ;
424429 let baud = config. baudrate . 0 ;
425430
426- // The frequency to calculate USARTDIV is this:
427- //
428- // (Taken from STM32F411xC/E Reference Manual,
429- // Section 19.3.4, Equation 1)
430- //
431- // 16 bit oversample: OVER8 = 0
432- // 8 bit oversample: OVER8 = 1
433- //
434- // USARTDIV = (pclk)
435- // ------------------------
436- // 8 x (2 - OVER8) x (baud)
437- //
438- // BUT, the USARTDIV has 4 "fractional" bits, which effectively
439- // means that we need to "correct" the equation as follows:
440- //
441- // USARTDIV = (pclk) * 16
442- // ------------------------
443- // 8 x (2 - OVER8) x (baud)
444- //
445- // When OVER8 is enabled, we can only use the lowest three
446- // fractional bits, so we'll need to shift those last four bits
447- // right one bit
448-
449- // Calculate correct baudrate divisor on the fly
450- let ( over8, div) = if ( pclk_freq / 16 ) >= baud {
451- // We have the ability to oversample to 16 bits, take
452- // advantage of it.
453- //
454- // We also add `baud / 2` to the `pclk_freq` to ensure
455- // rounding of values to the closest scale, rather than the
456- // floored behavior of normal integer division.
457- let div = ( pclk_freq + ( baud / 2 ) ) / baud;
458- ( false , div)
459- } else if ( pclk_freq / 8 ) >= baud {
460- // We are close enough to pclk where we can only
461- // oversample 8.
462- //
463- // See note above regarding `baud` and rounding.
464- let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
465-
466- // Ensure the the fractional bits (only 3) are
467- // right-aligned.
468- let frac = div & 0xF ;
469- let div = ( div & !0xF ) | ( frac >> 1 ) ;
470- ( true , div)
471- } else {
472- return Err ( config:: InvalidConfig ) ;
473- } ;
431+ let ( over8, div) = Self :: calculate_brr ( pclk_freq, baud) ?;
474432
475433 uart. brr ( ) . write ( |w| unsafe { w. bits ( div) } ) ;
476434
@@ -491,12 +449,7 @@ where {
491449 w. ps ( ) . bit ( config. parity == Parity :: ParityOdd )
492450 } ) ;
493451
494- match config. dma {
495- DmaConfig :: Tx => uart. cr3 ( ) . write ( |w| w. dmat ( ) . enabled ( ) ) ,
496- DmaConfig :: Rx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) ) ,
497- DmaConfig :: TxRx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) . dmat ( ) . enabled ( ) ) ,
498- DmaConfig :: None => { }
499- }
452+ uart. enable_dma ( config. dma ) ;
500453
501454 let serial = Serial {
502455 tx : Tx :: new ( uart, pins. 0 . into ( ) ) ,
0 commit comments