Skip to content

Commit 1371587

Browse files
author
James Munns
committed
Correct Serial Baudrate calculation
1 parent e809257 commit 1371587

File tree

1 file changed

+50
-3
lines changed

1 file changed

+50
-3
lines changed

src/serial.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)