Skip to content

Commit 6ee8859

Browse files
committed
Add uart test
1 parent 120404d commit 6ee8859

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

testsuite/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ name = "testsuite"
44
publish = false
55
version = "0.0.0"
66

7+
[[test]]
8+
name = "uart"
9+
harness = false
10+
711
[[test]]
812
name = "rcc"
913
harness = false
@@ -33,6 +37,7 @@ defmt-test = "0.2.0"
3337
# TODO: Set stm32f303xc as default, but make it overwritable
3438
stm32f3xx-hal = { path = "..", features = ["rt","defmt-trace","can", "ld"]}
3539
panic-probe = { version = "0.2.0", features = ["print-defmt"] }
40+
nb = "1.0.0"
3641

3742
[features]
3843
# enable all defmt logging levels

testsuite/tests/uart.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
// TODO: Get pa9 and pa10 because these also implement spi and uart
5+
use defmt_rtt as _;
6+
use panic_probe as _;
7+
8+
use stm32f3xx_hal as hal;
9+
10+
use hal::gpio::{
11+
gpioa::{PA10, PA2, PA3, PA9},
12+
gpiob::{PB10, PB11},
13+
};
14+
use hal::gpio::{OpenDrain, PushPull, AF7};
15+
use hal::pac;
16+
use hal::prelude::*;
17+
use hal::serial::{Rx, Serial, Tx};
18+
19+
use core::array::IntoIter;
20+
21+
use hal::serial::Error;
22+
23+
struct State {
24+
serial1: Option<Serial<pac::USART1, (PA9<AF7<PushPull>>, PA10<AF7<PushPull>>)>>,
25+
serial_slow: Option<Serial<pac::USART2, (PA2<AF7<PushPull>>, PA3<AF7<OpenDrain>>)>>,
26+
serial_fast: Option<Serial<pac::USART3, (PB10<AF7<PushPull>>, PB11<AF7<OpenDrain>>)>>,
27+
}
28+
29+
const TEST_MSG: [u8; 8] = [0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF];
30+
31+
#[defmt_test::tests]
32+
mod tests {
33+
use super::*;
34+
use defmt::{self, assert, assert_eq, unwrap};
35+
36+
#[init]
37+
fn init() -> super::State {
38+
let dp = unwrap!(pac::Peripherals::take());
39+
40+
let mut rcc = dp.RCC.constrain();
41+
let mut flash = dp.FLASH.constrain();
42+
let clocks = rcc.cfgr.freeze(&mut flash.acr);
43+
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
44+
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
45+
46+
let pins1 = (
47+
gpioa
48+
.pa9
49+
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
50+
gpioa
51+
.pa10
52+
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
53+
);
54+
let pins2 = (
55+
gpioa
56+
.pa2
57+
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl),
58+
gpioa
59+
.pa3
60+
.into_af7_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl),
61+
);
62+
let pins3 = (
63+
gpiob
64+
.pb10
65+
.into_af7_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh),
66+
gpiob
67+
.pb11
68+
.into_af7_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh),
69+
);
70+
71+
super::State {
72+
serial1: Some(Serial::usart1(
73+
dp.USART1,
74+
pins1,
75+
9600.Bd(),
76+
clocks,
77+
&mut rcc.apb2,
78+
)),
79+
serial_slow: Some(Serial::usart2(
80+
dp.USART2,
81+
pins2,
82+
57600.Bd(),
83+
clocks,
84+
&mut rcc.apb1,
85+
)),
86+
serial_fast: Some(Serial::usart3(
87+
dp.USART3,
88+
pins3,
89+
115200.Bd(),
90+
clocks,
91+
&mut rcc.apb1,
92+
)),
93+
}
94+
95+
// super::State { serial, clocks, apb2: rcc.apb2 }
96+
}
97+
98+
// Problems:
99+
// 1. if we split, we can not join (no runtime informatino which pins where associated with the
100+
// uart)
101+
// 2. if we free, we could crate a new one,
102+
// 3. but to use the serial we **have** to split, so this is useless
103+
// 4. So we have to implement join and than split on the whole uart to gain the uart + pins again.
104+
// 5. We should introduce the builder pattern (config pattern instead of dirtctl setting the
105+
// buad rate)
106+
// 6. No way to set parity etc.
107+
// 7. We have to implement read and write directly on the peripheral
108+
// - Maybe this should also follow
109+
//
110+
// #[test]
111+
// fn send_receive_split_fast(state: &mut super::State) {
112+
// let (usart, pins) = unwrap!(state.serial1.take()).free();
113+
// let mut serial = Serial::usart1(usart, pins, 115200.Bd(), state.clocks, &mut state.apb2);
114+
// let (mut tx, mut rx) = serial.split();
115+
// for i in &TEST_MSG {
116+
// nb::block!(tx.write(*i));
117+
// let c = unwrap!(nb::block!(rx.read()));
118+
// assert_eq!(c, *i);
119+
// }
120+
121+
// state.serial = Some(serial);
122+
// }
123+
124+
#[test]
125+
fn send_receive_split(state: &mut super::State) {
126+
let (mut tx, mut rx) = unwrap!(state.serial1.take()).split();
127+
for i in IntoIter::new(TEST_MSG) {
128+
defmt::unwrap!(nb::block!(tx.write(i)));
129+
let c = unwrap!(nb::block!(rx.read()));
130+
assert_eq!(c, i);
131+
}
132+
133+
// now provoke an overrun
134+
// send 5 u8 bytes, which do not fit in the 32 bit buffer
135+
for i in &TEST_MSG[..4] {
136+
defmt::unwrap!(nb::block!(tx.write(*i)));
137+
}
138+
let c = nb::block!(rx.read());
139+
assert!(matches!(c, Err(Error::Overrun)));
140+
}
141+
142+
#[test]
143+
fn send_receive_wrong_baud(state: &mut super::State) {
144+
let (mut tx_slow, mut rx_slow) = unwrap!(state.serial_slow.take()).split();
145+
let (mut tx_fast, mut rx_fast) = unwrap!(state.serial_fast.take()).split();
146+
147+
// provoke an error (framing)
148+
defmt::unwrap!(nb::block!(tx_slow.write(b'a')));
149+
let c = nb::block!(rx_fast.read());
150+
defmt::info!("{}", c);
151+
assert!(matches!(c, Err(Error::Framing)));
152+
153+
// provoke an error (framing)
154+
nb::block!(tx_fast.write(b'a'));
155+
let c = nb::block!(rx_slow.read());
156+
defmt::info!("{}", c);
157+
assert!(matches!(c, Err(Error::Framing)));
158+
}
159+
}

0 commit comments

Comments
 (0)