aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/mod.rs129
1 files changed, 36 insertions, 93 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index dc73de0c7..6bde827b9 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1513,10 +1513,12 @@ fn set_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), C
1513 Ok(()) 1513 Ok(())
1514} 1514}
1515 1515
1516fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), ConfigError> { 1516fn find_and_set_brr(
1517 let r = info.regs; 1517 r: stm32_metapac::usart::Usart,
1518 let kind = info.kind; 1518 kind: Kind,
1519 1519 kernel_clock: Hertz,
1520 baudrate: u32,
1521) -> Result<bool, ConfigError> {
1520 #[cfg(not(usart_v4))] 1522 #[cfg(not(usart_v4))]
1521 static DIVS: [(u16, ()); 1] = [(1, ())]; 1523 static DIVS: [(u16, ()); 1] = [(1, ())];
1522 1524
@@ -1548,12 +1550,8 @@ fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result
1548 } 1550 }
1549 }; 1551 };
1550 1552
1551 r.cr1().modify(|w| {
1552 // disable uart
1553 w.set_ue(false);
1554 });
1555
1556 let mut found_brr = None; 1553 let mut found_brr = None;
1554 let mut over8 = false;
1557 for &(presc, _presc_val) in &DIVS { 1555 for &(presc, _presc_val) in &DIVS {
1558 let brr = calculate_brr(baudrate, kernel_clock.0, presc as u32, mul); 1556 let brr = calculate_brr(baudrate, kernel_clock.0, presc as u32, mul);
1559 trace!( 1557 trace!(
@@ -1567,6 +1565,7 @@ fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result
1567 if brr < brr_min { 1565 if brr < brr_min {
1568 #[cfg(not(usart_v1))] 1566 #[cfg(not(usart_v1))]
1569 if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) { 1567 if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
1568 over8 = true;
1570 r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07))); 1569 r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07)));
1571 #[cfg(usart_v4)] 1570 #[cfg(usart_v4)]
1572 r.presc().write(|w| w.set_prescaler(_presc_val)); 1571 r.presc().write(|w| w.set_prescaler(_presc_val));
@@ -1585,17 +1584,38 @@ fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result
1585 } 1584 }
1586 } 1585 }
1587 1586
1588 let brr = found_brr.ok_or(ConfigError::BaudrateTooLow)?; 1587 match found_brr {
1588 Some(brr) => {
1589 #[cfg(not(usart_v1))]
1590 let oversampling = if over8 { "8 bit" } else { "16 bit" };
1591 #[cfg(usart_v1)]
1592 let oversampling = "default";
1593 trace!(
1594 "Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
1595 oversampling,
1596 baudrate,
1597 kernel_clock.0 / brr * mul
1598 );
1599 Ok(over8)
1600 }
1601 None => Err(ConfigError::BaudrateTooLow),
1602 }
1603}
1589 1604
1590 trace!( 1605fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), ConfigError> {
1591 "Desired baudrate: {}, actual baudrate: {}", 1606 let r = info.regs;
1592 baudrate, 1607 r.cr1().modify(|w| {
1593 kernel_clock.0 / brr * mul 1608 // disable uart
1594 ); 1609 w.set_ue(false);
1610 });
1611 let over8 = find_and_set_brr(r, info.kind, kernel_clock, baudrate)?;
1595 1612
1596 r.cr1().modify(|w| { 1613 r.cr1().modify(|w| {
1597 // enable uart 1614 // enable uart
1598 w.set_ue(true); 1615 w.set_ue(true);
1616
1617 #[cfg(not(usart_v1))]
1618 w.set_over8(vals::Over8::from_bits(over8 as _));
1599 }); 1619 });
1600 1620
1601 Ok(()) 1621 Ok(())
@@ -1615,89 +1635,12 @@ fn configure(
1615 return Err(ConfigError::RxOrTxNotEnabled); 1635 return Err(ConfigError::RxOrTxNotEnabled);
1616 } 1636 }
1617 1637
1618 #[cfg(not(usart_v4))]
1619 static DIVS: [(u16, ()); 1] = [(1, ())];
1620
1621 #[cfg(usart_v4)]
1622 static DIVS: [(u16, vals::Presc); 12] = [
1623 (1, vals::Presc::DIV1),
1624 (2, vals::Presc::DIV2),
1625 (4, vals::Presc::DIV4),
1626 (6, vals::Presc::DIV6),
1627 (8, vals::Presc::DIV8),
1628 (10, vals::Presc::DIV10),
1629 (12, vals::Presc::DIV12),
1630 (16, vals::Presc::DIV16),
1631 (32, vals::Presc::DIV32),
1632 (64, vals::Presc::DIV64),
1633 (128, vals::Presc::DIV128),
1634 (256, vals::Presc::DIV256),
1635 ];
1636
1637 let (mul, brr_min, brr_max) = match kind {
1638 #[cfg(any(usart_v3, usart_v4))]
1639 Kind::Lpuart => {
1640 trace!("USART: Kind::Lpuart");
1641 (256, 0x300, 0x10_0000)
1642 }
1643 Kind::Uart => {
1644 trace!("USART: Kind::Uart");
1645 (1, 0x10, 0x1_0000)
1646 }
1647 };
1648
1649 // UART must be disabled during configuration. 1638 // UART must be disabled during configuration.
1650 r.cr1().modify(|w| { 1639 r.cr1().modify(|w| {
1651 w.set_ue(false); 1640 w.set_ue(false);
1652 }); 1641 });
1653 1642
1654 #[cfg(not(usart_v1))] 1643 let over8 = find_and_set_brr(r, kind, kernel_clock, config.baudrate)?;
1655 let mut over8 = false;
1656 let mut found_brr = None;
1657 for &(presc, _presc_val) in &DIVS {
1658 let brr = calculate_brr(config.baudrate, kernel_clock.0, presc as u32, mul);
1659 trace!(
1660 "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})",
1661 presc,
1662 brr,
1663 brr >> 4,
1664 brr & 0x0F
1665 );
1666
1667 if brr < brr_min {
1668 #[cfg(not(usart_v1))]
1669 if brr * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
1670 over8 = true;
1671 r.brr().write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07)));
1672 #[cfg(usart_v4)]
1673 r.presc().write(|w| w.set_prescaler(_presc_val));
1674 found_brr = Some(brr);
1675 break;
1676 }
1677 return Err(ConfigError::BaudrateTooHigh);
1678 }
1679
1680 if brr < brr_max {
1681 r.brr().write_value(regs::Brr(brr));
1682 #[cfg(usart_v4)]
1683 r.presc().write(|w| w.set_prescaler(_presc_val));
1684 found_brr = Some(brr);
1685 break;
1686 }
1687 }
1688
1689 let brr = found_brr.ok_or(ConfigError::BaudrateTooLow)?;
1690
1691 #[cfg(not(usart_v1))]
1692 let oversampling = if over8 { "8 bit" } else { "16 bit" };
1693 #[cfg(usart_v1)]
1694 let oversampling = "default";
1695 trace!(
1696 "Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
1697 oversampling,
1698 config.baudrate,
1699 kernel_clock.0 / brr * mul
1700 );
1701 1644
1702 r.cr2().write(|w| { 1645 r.cr2().write(|w| {
1703 w.set_stop(match config.stop_bits { 1646 w.set_stop(match config.stop_bits {