diff options
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 129 |
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 | ||
| 1516 | fn set_usart_baudrate(info: &Info, kernel_clock: Hertz, baudrate: u32) -> Result<(), ConfigError> { | 1516 | fn 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!( | 1605 | fn 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 { |
