aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-02 20:14:12 +0000
committerGitHub <[email protected]>2023-05-02 20:14:12 +0000
commit374c92a4f0fda2932a0a86e5dcc3dc33651a48c7 (patch)
treeac320229c9371bc0d3b6deffda4671f502823f5c
parent2afa08c9236d386cae7920d9e7f20803a2c6b433 (diff)
parent433422b9f2b08d4bf9f2cef4ded37c14914db157 (diff)
Merge #1420
1420: stm32/usart: add OVER8 and PRESC, add baudrate test. r=Dirbaio a=Dirbaio Fixes #1183 Fixes #1418 bors r+ Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/usart/buffered.rs4
-rw-r--r--embassy-stm32/src/usart/mod.rs128
-rw-r--r--tests/stm32/Cargo.toml1
-rw-r--r--tests/stm32/build.rs13
-rw-r--r--tests/stm32/src/bin/spi.rs1
-rw-r--r--tests/stm32/src/bin/usart.rs77
-rw-r--r--tests/stm32/src/bin/usart_dma.rs3
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs7
-rw-r--r--tests/stm32/src/example_common.rs5
10 files changed, 182 insertions, 61 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 9686b10ce..b9887f9b3 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,7 @@ sdio-host = "0.5.0"
58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
59critical-section = "1.1" 59critical-section = "1.1"
60atomic-polyfill = "1.0.1" 60atomic-polyfill = "1.0.1"
61stm32-metapac = "6" 61stm32-metapac = "7"
62vcell = "0.1.3" 62vcell = "0.1.3"
63bxcan = "0.7.0" 63bxcan = "0.7.0"
64nb = "1.0.0" 64nb = "1.0.0"
@@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] }
74[build-dependencies] 74[build-dependencies]
75proc-macro2 = "1.0.36" 75proc-macro2 = "1.0.36"
76quote = "1.0.15" 76quote = "1.0.15"
77stm32-metapac = { version = "6", default-features = false, features = ["metadata"]} 77stm32-metapac = { version = "7", default-features = false, features = ["metadata"]}
78 78
79[features] 79[features]
80default = ["stm32-metapac/rt"] 80default = ["stm32-metapac/rt"]
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 3e23e7ca1..12cf8b0fc 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -84,7 +84,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
84 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config) 84 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
85 } 85 }
86 86
87 #[cfg(not(usart_v1))] 87 #[cfg(not(any(usart_v1, usart_v2)))]
88 pub fn new_with_de( 88 pub fn new_with_de(
89 peri: impl Peripheral<P = T> + 'd, 89 peri: impl Peripheral<P = T> + 'd,
90 irq: impl Peripheral<P = T::Interrupt> + 'd, 90 irq: impl Peripheral<P = T::Interrupt> + 'd,
@@ -133,7 +133,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
133 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 133 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
134 } 134 }
135 135
136 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true); 136 configure(r, &config, T::frequency(), T::KIND, true, true);
137 137
138 unsafe { 138 unsafe {
139 r.cr1().modify(|w| { 139 r.cr1().modify(|w| {
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ad450f2b3..dbce668c2 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -12,10 +12,11 @@ use futures::future::{select, Either};
12 12
13use crate::dma::{NoDma, Transfer}; 13use crate::dma::{NoDma, Transfer};
14use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
15#[cfg(any(lpuart_v1, lpuart_v2))] 15#[cfg(not(any(usart_v1, usart_v2)))]
16use crate::pac::lpuart::{regs, vals, Lpuart as Regs}; 16use crate::pac::usart::Lpuart as Regs;
17#[cfg(not(any(lpuart_v1, lpuart_v2)))] 17#[cfg(any(usart_v1, usart_v2))]
18use crate::pac::usart::{regs, vals, Usart as Regs}; 18use crate::pac::usart::Usart as Regs;
19use crate::pac::usart::{regs, vals};
19use crate::time::Hertz; 20use crate::time::Hertz;
20use crate::{peripherals, Peripheral}; 21use crate::{peripherals, Peripheral};
21 22
@@ -159,7 +160,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
159 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 160 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
160 } 161 }
161 162
162 configure(r, &config, T::frequency(), T::MULTIPLIER, false, true); 163 configure(r, &config, T::frequency(), T::KIND, false, true);
163 164
164 // create state once! 165 // create state once!
165 let _s = T::state(); 166 let _s = T::state();
@@ -261,7 +262,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
261 rx.set_as_af(rx.af_num(), AFType::Input); 262 rx.set_as_af(rx.af_num(), AFType::Input);
262 } 263 }
263 264
264 configure(r, &config, T::frequency(), T::MULTIPLIER, true, false); 265 configure(r, &config, T::frequency(), T::KIND, true, false);
265 266
266 irq.set_handler(Self::on_interrupt); 267 irq.set_handler(Self::on_interrupt);
267 irq.unpend(); 268 irq.unpend();
@@ -653,7 +654,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
653 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config) 654 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
654 } 655 }
655 656
656 #[cfg(not(usart_v1))] 657 #[cfg(not(any(usart_v1, usart_v2)))]
657 pub fn new_with_de( 658 pub fn new_with_de(
658 peri: impl Peripheral<P = T> + 'd, 659 peri: impl Peripheral<P = T> + 'd,
659 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 660 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -696,7 +697,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
696 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 697 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
697 } 698 }
698 699
699 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true); 700 configure(r, &config, T::frequency(), T::KIND, true, true);
700 701
701 irq.set_handler(UartRx::<T, RxDma>::on_interrupt); 702 irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
702 irq.unpend(); 703 irq.unpend();
@@ -763,16 +764,74 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
763 } 764 }
764} 765}
765 766
766fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable_rx: bool, enable_tx: bool) { 767fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: bool, enable_tx: bool) {
767 if !enable_rx && !enable_tx { 768 if !enable_rx && !enable_tx {
768 panic!("USART: At least one of RX or TX should be enabled"); 769 panic!("USART: At least one of RX or TX should be enabled");
769 } 770 }
770 771
771 // TODO: better calculation, including error checking and OVER8 if possible. 772 #[cfg(not(usart_v4))]
772 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier; 773 static DIVS: [(u16, ()); 1] = [(1, ())];
774
775 #[cfg(usart_v4)]
776 static DIVS: [(u16, vals::Presc); 12] = [
777 (1, vals::Presc::DIV1),
778 (2, vals::Presc::DIV2),
779 (4, vals::Presc::DIV4),
780 (6, vals::Presc::DIV6),
781 (8, vals::Presc::DIV8),
782 (10, vals::Presc::DIV10),
783 (12, vals::Presc::DIV12),
784 (16, vals::Presc::DIV16),
785 (32, vals::Presc::DIV32),
786 (64, vals::Presc::DIV64),
787 (128, vals::Presc::DIV128),
788 (256, vals::Presc::DIV256),
789 ];
790
791 let (mul, brr_min, brr_max) = match kind {
792 #[cfg(any(usart_v3, usart_v4))]
793 Kind::Lpuart => (256, 0x300, 0x10_0000),
794 Kind::Uart => (1, 0x10, 0x1_0000),
795 };
796
797 #[cfg(not(usart_v1))]
798 let mut over8 = false;
799 let mut found = false;
800 for &(presc, _presc_val) in &DIVS {
801 let denom = (config.baudrate * presc as u32) as u64;
802 let div = (pclk_freq.0 as u64 * mul + (denom / 2)) / denom;
803 trace!("USART: presc={} div={:08x}", presc, div);
804
805 if div < brr_min {
806 #[cfg(not(usart_v1))]
807 if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
808 over8 = true;
809 let div = div as u32;
810 unsafe {
811 r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
812 #[cfg(usart_v4)]
813 r.presc().write(|w| w.set_prescaler(_presc_val));
814 }
815 found = true;
816 break;
817 }
818 panic!("USART: baudrate too high");
819 }
820
821 if div < brr_max {
822 unsafe {
823 r.brr().write_value(regs::Brr(div as u32));
824 #[cfg(usart_v4)]
825 r.presc().write(|w| w.set_prescaler(_presc_val));
826 }
827 found = true;
828 break;
829 }
830 }
831
832 assert!(found, "USART: baudrate too low");
773 833
774 unsafe { 834 unsafe {
775 r.brr().write_value(regs::Brr(div));
776 r.cr2().write(|w| { 835 r.cr2().write(|w| {
777 w.set_stop(match config.stop_bits { 836 w.set_stop(match config.stop_bits {
778 StopBits::STOP0P5 => vals::Stop::STOP0P5, 837 StopBits::STOP0P5 => vals::Stop::STOP0P5,
@@ -801,6 +860,8 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable
801 Parity::ParityEven => vals::Ps::EVEN, 860 Parity::ParityEven => vals::Ps::EVEN,
802 _ => vals::Ps::EVEN, 861 _ => vals::Ps::EVEN,
803 }); 862 });
863 #[cfg(not(usart_v1))]
864 w.set_over8(vals::Over8(over8 as _));
804 }); 865 });
805 } 866 }
806} 867}
@@ -986,43 +1047,45 @@ mod rx_ringbuffered;
986#[cfg(not(gpdma))] 1047#[cfg(not(gpdma))]
987pub use rx_ringbuffered::RingBufferedUartRx; 1048pub use rx_ringbuffered::RingBufferedUartRx;
988 1049
989#[cfg(usart_v1)] 1050use self::sealed::Kind;
1051
1052#[cfg(any(usart_v1, usart_v2))]
990fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 1053fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
991 r.dr().ptr() as _ 1054 r.dr().ptr() as _
992} 1055}
993 1056
994#[cfg(usart_v1)] 1057#[cfg(any(usart_v1, usart_v2))]
995fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { 1058fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
996 r.dr().ptr() as _ 1059 r.dr().ptr() as _
997} 1060}
998 1061
999#[cfg(usart_v1)] 1062#[cfg(any(usart_v1, usart_v2))]
1000fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> { 1063fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> {
1001 r.sr() 1064 r.sr()
1002} 1065}
1003 1066
1004#[cfg(usart_v1)] 1067#[cfg(any(usart_v1, usart_v2))]
1005#[allow(unused)] 1068#[allow(unused)]
1006unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { 1069unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
1007 // On v1 the flags are cleared implicitly by reads and writes to DR. 1070 // On v1 the flags are cleared implicitly by reads and writes to DR.
1008} 1071}
1009 1072
1010#[cfg(usart_v2)] 1073#[cfg(any(usart_v3, usart_v4))]
1011fn tdr(r: Regs) -> *mut u8 { 1074fn tdr(r: Regs) -> *mut u8 {
1012 r.tdr().ptr() as _ 1075 r.tdr().ptr() as _
1013} 1076}
1014 1077
1015#[cfg(usart_v2)] 1078#[cfg(any(usart_v3, usart_v4))]
1016fn rdr(r: Regs) -> *mut u8 { 1079fn rdr(r: Regs) -> *mut u8 {
1017 r.rdr().ptr() as _ 1080 r.rdr().ptr() as _
1018} 1081}
1019 1082
1020#[cfg(usart_v2)] 1083#[cfg(any(usart_v3, usart_v4))]
1021fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> { 1084fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> {
1022 r.isr() 1085 r.isr()
1023} 1086}
1024 1087
1025#[cfg(usart_v2)] 1088#[cfg(any(usart_v3, usart_v4))]
1026#[allow(unused)] 1089#[allow(unused)]
1027unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { 1090unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
1028 r.icr().write(|w| *w = regs::Icr(sr.0)); 1091 r.icr().write(|w| *w = regs::Icr(sr.0));
@@ -1033,6 +1096,13 @@ pub(crate) mod sealed {
1033 1096
1034 use super::*; 1097 use super::*;
1035 1098
1099 #[derive(Clone, Copy, PartialEq, Eq)]
1100 pub enum Kind {
1101 Uart,
1102 #[cfg(any(usart_v3, usart_v4))]
1103 Lpuart,
1104 }
1105
1036 pub struct State { 1106 pub struct State {
1037 pub rx_waker: AtomicWaker, 1107 pub rx_waker: AtomicWaker,
1038 pub tx_waker: AtomicWaker, 1108 pub tx_waker: AtomicWaker,
@@ -1048,7 +1118,7 @@ pub(crate) mod sealed {
1048 } 1118 }
1049 1119
1050 pub trait BasicInstance: crate::rcc::RccPeripheral { 1120 pub trait BasicInstance: crate::rcc::RccPeripheral {
1051 const MULTIPLIER: u32; 1121 const KIND: Kind;
1052 type Interrupt: crate::interrupt::Interrupt; 1122 type Interrupt: crate::interrupt::Interrupt;
1053 1123
1054 fn regs() -> Regs; 1124 fn regs() -> Regs;
@@ -1077,10 +1147,10 @@ pin_trait!(DePin, BasicInstance);
1077dma_trait!(TxDma, BasicInstance); 1147dma_trait!(TxDma, BasicInstance);
1078dma_trait!(RxDma, BasicInstance); 1148dma_trait!(RxDma, BasicInstance);
1079 1149
1080macro_rules! impl_lpuart { 1150macro_rules! impl_usart {
1081 ($inst:ident, $irq:ident, $mul:expr) => { 1151 ($inst:ident, $irq:ident, $kind:expr) => {
1082 impl sealed::BasicInstance for crate::peripherals::$inst { 1152 impl sealed::BasicInstance for crate::peripherals::$inst {
1083 const MULTIPLIER: u32 = $mul; 1153 const KIND: Kind = $kind;
1084 type Interrupt = crate::interrupt::$irq; 1154 type Interrupt = crate::interrupt::$irq;
1085 1155
1086 fn regs() -> Regs { 1156 fn regs() -> Regs {
@@ -1104,21 +1174,19 @@ macro_rules! impl_lpuart {
1104} 1174}
1105 1175
1106foreach_interrupt!( 1176foreach_interrupt!(
1107 ($inst:ident, lpuart, $block:ident, $signal_name:ident, $irq:ident) => { 1177 ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => {
1108 impl_lpuart!($inst, $irq, 256); 1178 impl_usart!($inst, $irq, Kind::Lpuart);
1109 }; 1179 };
1110 1180
1111 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { 1181 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
1112 impl_lpuart!($inst, $irq, 1); 1182 impl_usart!($inst, $irq, Kind::Uart);
1113 1183
1114 impl sealed::FullInstance for peripherals::$inst { 1184 impl sealed::FullInstance for peripherals::$inst {
1115
1116 fn regs_uart() -> crate::pac::usart::Usart { 1185 fn regs_uart() -> crate::pac::usart::Usart {
1117 crate::pac::$inst 1186 crate::pac::$inst
1118 } 1187 }
1119 } 1188 }
1120 1189
1121 impl FullInstance for peripherals::$inst { 1190 impl FullInstance for peripherals::$inst {}
1122 }
1123 }; 1191 };
1124); 1192);
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 5cd949661..83bf1e9c9 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2021"
3name = "embassy-stm32-tests" 3name = "embassy-stm32-tests"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6autobins = false
6 7
7[features] 8[features]
8stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill 9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill
diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs
index 3e67a7392..7ae311778 100644
--- a/tests/stm32/build.rs
+++ b/tests/stm32/build.rs
@@ -6,15 +6,16 @@ fn main() -> Result<(), Box<dyn Error>> {
6 let out = PathBuf::from(env::var("OUT_DIR").unwrap()); 6 let out = PathBuf::from(env::var("OUT_DIR").unwrap());
7 fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); 7 fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap();
8 println!("cargo:rustc-link-search={}", out.display()); 8 println!("cargo:rustc-link-search={}", out.display());
9 println!("cargo:rerun-if-changed=link_ram.x");
10
11 println!("cargo:rustc-link-arg-bins=--nmagic"); 9 println!("cargo:rustc-link-arg-bins=--nmagic");
12 10
13 // too little RAM to run from RAM. 11 // too little RAM to run from RAM.
14 #[cfg(any(feature = "stm32c031c6"))] 12 if cfg!(any(feature = "stm32f103c8", feature = "stm32c031c6")) {
15 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 13 println!("cargo:rustc-link-arg-bins=-Tlink.x");
16 #[cfg(not(any(feature = "stm32c031c6")))] 14 println!("cargo:rerun-if-changed=link.x");
17 println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); 15 } else {
16 println!("cargo:rustc-link-arg-bins=-Tlink_ram.x");
17 println!("cargo:rerun-if-changed=link_ram.x");
18 }
18 19
19 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 20 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
20 21
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index 0f5e563b1..a87ac3237 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -35,7 +35,6 @@ async fn main(_spawner: Spawner) {
35 #[cfg(feature = "stm32c031c6")] 35 #[cfg(feature = "stm32c031c6")]
36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6); 36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6);
37 37
38 info!("asdfa;");
39 let mut spi = Spi::new( 38 let mut spi = Spi::new(
40 spi, 39 spi,
41 sck, // Arduino D13 40 sck, // Arduino D13
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index cca8c42ee..bda2ce9c2 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -9,6 +9,7 @@ use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
12use embassy_time::{Duration, Instant};
12use example_common::*; 13use example_common::*;
13 14
14#[embassy_executor::main] 15#[embassy_executor::main]
@@ -19,36 +20,76 @@ async fn main(_spawner: Spawner) {
19 // Arduino pins D0 and D1 20 // Arduino pins D0 and D1
20 // They're connected together with a 1K resistor. 21 // They're connected together with a 1K resistor.
21 #[cfg(feature = "stm32f103c8")] 22 #[cfg(feature = "stm32f103c8")]
22 let (tx, rx, usart, irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1)); 23 let (mut tx, mut rx, mut usart, mut irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
23 #[cfg(feature = "stm32g491re")] 24 #[cfg(feature = "stm32g491re")]
24 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 25 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
25 #[cfg(feature = "stm32g071rb")] 26 #[cfg(feature = "stm32g071rb")]
26 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 27 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
27 #[cfg(feature = "stm32f429zi")] 28 #[cfg(feature = "stm32f429zi")]
28 let (tx, rx, usart, irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6)); 29 let (mut tx, mut rx, mut usart, mut irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
29 #[cfg(feature = "stm32wb55rg")] 30 #[cfg(feature = "stm32wb55rg")]
30 let (tx, rx, usart, irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1)); 31 let (mut tx, mut rx, mut usart, mut irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
31 #[cfg(feature = "stm32h755zi")] 32 #[cfg(feature = "stm32h755zi")]
32 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 33 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
33 #[cfg(feature = "stm32u585ai")] 34 #[cfg(feature = "stm32u585ai")]
34 let (tx, rx, usart, irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3)); 35 let (mut tx, mut rx, mut usart, mut irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
35 #[cfg(feature = "stm32h563zi")] 36 #[cfg(feature = "stm32h563zi")]
36 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1)); 37 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1));
37 #[cfg(feature = "stm32c031c6")] 38 #[cfg(feature = "stm32c031c6")]
38 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 39 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
39 40
40 let config = Config::default(); 41 {
41 let mut usart = Uart::new(usart, rx, tx, irq, NoDma, NoDma, config); 42 let config = Config::default();
43 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
42 44
43 // We can't send too many bytes, they have to fit in the FIFO. 45 // We can't send too many bytes, they have to fit in the FIFO.
44 // This is because we aren't sending+receiving at the same time. 46 // This is because we aren't sending+receiving at the same time.
45 47
46 let data = [0xC0, 0xDE]; 48 let data = [0xC0, 0xDE];
47 usart.blocking_write(&data).unwrap(); 49 usart.blocking_write(&data).unwrap();
48 50
49 let mut buf = [0; 2]; 51 let mut buf = [0; 2];
50 usart.blocking_read(&mut buf).unwrap(); 52 usart.blocking_read(&mut buf).unwrap();
51 assert_eq!(buf, data); 53 assert_eq!(buf, data);
54 }
55
56 // Test that baudrate divider is calculated correctly.
57 // Do it by comparing the time it takes to send a known number of bytes.
58 for baudrate in [
59 300,
60 9600,
61 115200,
62 250_000,
63 337_934,
64 #[cfg(not(feature = "stm32f103c8"))]
65 1_000_000,
66 #[cfg(not(feature = "stm32f103c8"))]
67 2_000_000,
68 ] {
69 info!("testing baudrate {}", baudrate);
70
71 let mut config = Config::default();
72 config.baudrate = baudrate;
73 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
74
75 let n = (baudrate as usize / 100).max(64);
76
77 let start = Instant::now();
78 for _ in 0..n {
79 usart.blocking_write(&[0x00]).unwrap();
80 }
81 let dur = Instant::now() - start;
82 let want_dur = Duration::from_micros(n as u64 * 10 * 1_000_000 / (baudrate as u64));
83 let fuzz = want_dur / 5;
84 if dur < want_dur - fuzz || dur > want_dur + fuzz {
85 defmt::panic!(
86 "bad duration for baudrate {}: got {:?} want {:?}",
87 baudrate,
88 dur,
89 want_dur
90 );
91 }
92 }
52 93
53 info!("Test OK"); 94 info!("Test OK");
54 cortex_m::asm::bkpt(); 95 cortex_m::asm::bkpt();
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index de6cd41d1..62444f0a8 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -94,6 +94,9 @@ async fn main(_spawner: Spawner) {
94 let rx_fut = async { 94 let rx_fut = async {
95 rx.read(&mut rx_buf).await.unwrap(); 95 rx.read(&mut rx_buf).await.unwrap();
96 }; 96 };
97
98 // note: rx needs to be polled first, to workaround this bug:
99 // https://github.com/embassy-rs/embassy/issues/1426
97 join(rx_fut, tx_fut).await; 100 join(rx_fut, tx_fut).await;
98 101
99 assert_eq!(tx_buf, rx_buf); 102 assert_eq!(tx_buf, rx_buf);
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
index 2c4a8fdf4..9d75dbe55 100644
--- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs
+++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
@@ -145,13 +145,16 @@ async fn main(spawner: Spawner) {
145 145
146#[embassy_executor::task] 146#[embassy_executor::task]
147async fn transmit_task(mut tx: UartTx<'static, board::Uart, board::TxDma>) { 147async fn transmit_task(mut tx: UartTx<'static, board::Uart, board::TxDma>) {
148 // workaround https://github.com/embassy-rs/embassy/issues/1426
149 Timer::after(Duration::from_millis(100) as _).await;
150
148 let mut rng = ChaCha8Rng::seed_from_u64(1337); 151 let mut rng = ChaCha8Rng::seed_from_u64(1337);
149 152
150 info!("Starting random transmissions into void..."); 153 info!("Starting random transmissions into void...");
151 154
152 let mut i: u8 = 0; 155 let mut i: u8 = 0;
153 loop { 156 loop {
154 let mut buf = [0; 32]; 157 let mut buf = [0; 256];
155 let len = 1 + (rng.next_u32() as usize % buf.len()); 158 let len = 1 + (rng.next_u32() as usize % buf.len());
156 for b in &mut buf[..len] { 159 for b in &mut buf[..len] {
157 *b = i; 160 *b = i;
@@ -172,7 +175,7 @@ async fn receive_task(mut rx: RingBufferedUartRx<'static, board::Uart, board::Rx
172 let mut i = 0; 175 let mut i = 0;
173 let mut expected = 0; 176 let mut expected = 0;
174 loop { 177 loop {
175 let mut buf = [0; 100]; 178 let mut buf = [0; 256];
176 let max_len = 1 + (rng.next_u32() as usize % buf.len()); 179 let max_len = 1 + (rng.next_u32() as usize % buf.len());
177 let received = match rx.read(&mut buf[..max_len]).await { 180 let received = match rx.read(&mut buf[..max_len]).await {
178 Ok(r) => r, 181 Ok(r) => r,
diff --git a/tests/stm32/src/example_common.rs b/tests/stm32/src/example_common.rs
index a4f8668c7..3d150da60 100644
--- a/tests/stm32/src/example_common.rs
+++ b/tests/stm32/src/example_common.rs
@@ -16,5 +16,10 @@ pub fn config() -> Config {
16 config.rcc.pll1.q_ck = Some(Hertz(100_000_000)); 16 config.rcc.pll1.q_ck = Some(Hertz(100_000_000));
17 } 17 }
18 18
19 #[cfg(feature = "stm32u585ai")]
20 {
21 config.rcc.mux = embassy_stm32::rcc::ClockSrc::MSI(embassy_stm32::rcc::MSIRange::Range48mhz);
22 }
23
19 config 24 config
20} 25}