@@ -1424,10 +1424,55 @@ macro_rules! halUsartImpl {
1424
1424
bb:: set( & rcc. $apbXenr, $rcc_bit) ;
1425
1425
}
1426
1426
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
+
1427
1453
// 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
+ } ) ;
1431
1476
1432
1477
// Reset other registers to disable advanced USART features
1433
1478
usart. cr2. reset( ) ;
@@ -1438,6 +1483,8 @@ macro_rules! halUsartImpl {
1438
1483
usart. cr1. write( |w| {
1439
1484
w. ue( )
1440
1485
. set_bit( )
1486
+ . over8( )
1487
+ . bit( over8)
1441
1488
. te( )
1442
1489
. set_bit( )
1443
1490
. re( )
0 commit comments