@@ -1424,10 +1424,55 @@ macro_rules! halUsartImpl {
14241424 bb:: set( & rcc. $apbXenr, $rcc_bit) ;
14251425 }
14261426
1427+ let pclk_freq = clocks. $pclkX( ) . 0 ;
1428+ let baud = config. baudrate. 0 ;
1429+
1430+ // The frequency to calculate USARTDIV is this:
1431+ //
1432+ // (Taken from STM32F411xC/E Reference Manual,
1433+ // Section 19.3.4, Equation 1)
1434+ //
1435+ // 16 bit oversample: OVER8 = 0
1436+ // 8 bit oversample: OVER8 = 1
1437+ //
1438+ // USARTDIV = (pclk)
1439+ // ------------------------
1440+ // 8 x (2 - OVER8) x (baud)
1441+ //
1442+ // BUT, the USARTDIV has 4 "fractional" bits, which effectively
1443+ // means that we need to "correct" the equation as follows:
1444+ //
1445+ // USARTDIV = (pclk) * 16
1446+ // ------------------------
1447+ // 8 x (2 - OVER8) x (baud)
1448+ //
1449+ // When OVER8 is enabled, we can only use the lowest three
1450+ // fractional bits, so we'll need to shift those last four bits
1451+ // right one bit
1452+
14271453 // Calculate correct baudrate divisor on the fly
1428- let div = ( clocks. $pclkX( ) . 0 + config. baudrate. 0 / 2 )
1429- / config. baudrate. 0 ;
1430- usart. brr. write( |w| unsafe { w. bits( div) } ) ;
1454+ let ( over8, div) = if ( pclk_freq / 16 ) >= baud {
1455+ // We have the ability to oversample to 16 bits, take
1456+ // advantage of it.
1457+ let div = pclk_freq / baud;
1458+ ( false , div)
1459+ } else if ( pclk_freq / 8 ) >= baud {
1460+ // We are close enough to pclk where we can only
1461+ // oversample 8.
1462+ let div = ( pclk_freq * 2 ) / baud;
1463+
1464+ // Ensure the the fractional bits (only 3) are
1465+ // right-aligned.
1466+ let frac = ( div & 0xF ) ;
1467+ let div = ( div & !0xF ) | ( frac >> 1 ) ;
1468+ ( true , div)
1469+ } else {
1470+ return Err ( config:: InvalidConfig )
1471+ } ;
1472+
1473+ usart. brr. write( |w| unsafe {
1474+ w. bits( div)
1475+ } ) ;
14311476
14321477 // Reset other registers to disable advanced USART features
14331478 usart. cr2. reset( ) ;
@@ -1438,6 +1483,8 @@ macro_rules! halUsartImpl {
14381483 usart. cr1. write( |w| {
14391484 w. ue( )
14401485 . set_bit( )
1486+ . over8( )
1487+ . bit( over8)
14411488 . te( )
14421489 . set_bit( )
14431490 . re( )
0 commit comments