aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCorey Schuhen <[email protected]>2024-01-17 21:13:24 +1000
committerCorey Schuhen <[email protected]>2024-01-31 05:40:05 +1000
commit6e1047395d56dbbd1aa1a0352bdd3147e3994c5b (patch)
tree681520439b8e80cf36c3162c033d89484da276b0 /tests
parent1698f4dbc3b5f4e561c3edd20246af63c22da507 (diff)
HIL test for STM32 FDCAN support.
Internal loopback. fdcan: use common.rs for HIL test. Fix tests. Fix tests. Fix tests Add HIL tests for H7 even though they are a bit crippled. CI fixes Bah Test bah
Diffstat (limited to 'tests')
-rw-r--r--tests/stm32/Cargo.toml16
-rw-r--r--tests/stm32/src/bin/fdcan.rs243
2 files changed, 254 insertions, 5 deletions
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bf85f05d2..b8b52c076 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -14,11 +14,11 @@ stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not
14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"] 14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] 15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"] 16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"]
17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng"] 17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"]
18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"] 18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "fdcan"]
19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"] 19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan"]
20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng"] 20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan"]
21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng"] 21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"]
22stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"] 22stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"] 23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
24stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"] 24stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
@@ -37,6 +37,7 @@ sdmmc = []
37stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"] 37stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
38chrono = ["embassy-stm32/chrono", "dep:chrono"] 38chrono = ["embassy-stm32/chrono", "dep:chrono"]
39can = [] 39can = []
40fdcan = []
40ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] 41ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
41mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] 42mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
42embassy-stm32-wpan = [] 43embassy-stm32-wpan = []
@@ -97,6 +98,11 @@ path = "src/bin/eth.rs"
97required-features = [ "eth",] 98required-features = [ "eth",]
98 99
99[[bin]] 100[[bin]]
101name = "fdcan"
102path = "src/bin/fdcan.rs"
103required-features = [ "fdcan",]
104
105[[bin]]
100name = "gpio" 106name = "gpio"
101path = "src/bin/gpio.rs" 107path = "src/bin/gpio.rs"
102required-features = [] 108required-features = []
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
new file mode 100644
index 000000000..7363eaa16
--- /dev/null
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -0,0 +1,243 @@
1#![no_std]
2#![no_main]
3
4// required-features: fdcan
5
6#[path = "../common.rs"]
7mod common;
8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner;
11use embassy_stm32::peripherals::*;
12use embassy_stm32::{bind_interrupts, can, Config};
13use embassy_time::{Duration, Instant};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
18 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
19});
20
21struct TestOptions {
22 config: Config,
23 max_latency: Duration,
24 second_fifo_working: bool,
25}
26
27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
28fn options() -> TestOptions {
29 use embassy_stm32::rcc;
30 info!("H75 config");
31 let mut c = config();
32 c.rcc.hse = Some(rcc::Hse {
33 freq: embassy_stm32::time::Hertz(25_000_000),
34 mode: rcc::HseMode::Oscillator,
35 });
36 c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
37 TestOptions {
38 config: c,
39 max_latency: Duration::from_micros(3800),
40 second_fifo_working: false,
41 }
42}
43
44#[cfg(any(feature = "stm32h7a3zi"))]
45fn options() -> TestOptions {
46 use embassy_stm32::rcc;
47 info!("H7a config");
48 let mut c = config();
49 c.rcc.hse = Some(rcc::Hse {
50 freq: embassy_stm32::time::Hertz(25_000_000),
51 mode: rcc::HseMode::Oscillator,
52 });
53 c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
54 TestOptions {
55 config: c,
56 max_latency: Duration::from_micros(5500),
57 second_fifo_working: false,
58 }
59}
60
61#[cfg(any(feature = "stm32g491re"))]
62fn options() -> TestOptions {
63 info!("G4 config");
64 TestOptions {
65 config: config(),
66 max_latency: Duration::from_micros(500),
67 second_fifo_working: true,
68 }
69}
70
71#[embassy_executor::main]
72async fn main(_spawner: Spawner) {
73 //let peripherals = embassy_stm32::init(config());
74
75 let options = options();
76 let peripherals = embassy_stm32::init(options.config);
77
78 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs);
79
80 // 250k bps
81 can.set_bitrate(250_000);
82
83 can.can.set_extended_filter(
84 can::filter::ExtendedFilterSlot::_0,
85 can::filter::ExtendedFilter::accept_all_into_fifo1(),
86 );
87
88 let mut can = can.into_internal_loopback_mode();
89
90 info!("CAN Configured");
91
92 let mut i: u8 = 0;
93 loop {
94 let tx_frame = can::TxFrame::new(
95 can::TxFrameHeader {
96 len: 1,
97 frame_format: can::FrameFormat::Standard,
98 id: can::StandardId::new(0x123).unwrap().into(),
99 bit_rate_switching: false,
100 marker: None,
101 },
102 &[i],
103 )
104 .unwrap();
105
106 info!("Transmitting frame...");
107 let tx_ts = Instant::now();
108 can.write(&tx_frame).await;
109
110 let envelope = can.read().await.unwrap();
111 info!("Frame received!");
112
113 // Check data.
114 assert!(i == envelope.data()[0], "{} == {}", i, envelope.data()[0]);
115
116 info!("loopback time {}", envelope.header.time_stamp);
117 info!("loopback frame {=u8}", envelope.data()[0]);
118 let latency = envelope.timestamp.saturating_duration_since(tx_ts);
119 info!("loopback latency {} us", latency.as_micros());
120
121 // Theoretical minimum latency is 55us, actual is usually ~80us
122 const MIN_LATENCY: Duration = Duration::from_micros(50);
123 // Was failing at 150 but we are not getting a real time stamp. I'm not
124 // sure if there are other delays
125 assert!(
126 MIN_LATENCY <= latency && latency <= options.max_latency,
127 "{} <= {} <= {}",
128 MIN_LATENCY,
129 latency,
130 options.max_latency
131 );
132
133 i += 1;
134 if i > 10 {
135 break;
136 }
137 }
138
139 let max_buffered = if options.second_fifo_working { 6 } else { 3 };
140
141 // Below here, check that we can receive from both FIFO0 and FIFO0
142 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
143 // in each FIFO so make sure we write enough to fill them both up before reading.
144 for i in 0..3 {
145 // Try filling up the RX FIFO0 buffers with standard packets
146 let tx_frame = can::TxFrame::new(
147 can::TxFrameHeader {
148 len: 1,
149 frame_format: can::FrameFormat::Standard,
150 id: can::StandardId::new(0x123).unwrap().into(),
151 bit_rate_switching: false,
152 marker: None,
153 },
154 &[i],
155 )
156 .unwrap();
157 info!("Transmitting frame {}", i);
158 can.write(&tx_frame).await;
159 }
160 for i in 3..max_buffered {
161 // Try filling up the RX FIFO0 buffers with extended packets
162 let tx_frame = can::TxFrame::new(
163 can::TxFrameHeader {
164 len: 1,
165 frame_format: can::FrameFormat::Standard,
166 id: can::ExtendedId::new(0x1232344).unwrap().into(),
167 bit_rate_switching: false,
168 marker: None,
169 },
170 &[i],
171 )
172 .unwrap();
173
174 info!("Transmitting frame {}", i);
175 can.write(&tx_frame).await;
176 }
177
178 // Try and receive all 6 packets
179 for i in 0..max_buffered {
180 let envelope = can.read().await.unwrap();
181 match envelope.header.id {
182 can::Id::Extended(id) => {
183 info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
184 }
185 can::Id::Standard(id) => {
186 info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
187 }
188 }
189 }
190
191 // Test again with a split
192 let (mut tx, mut rx) = can.split();
193 for i in 0..3 {
194 // Try filling up the RX FIFO0 buffers with standard packets
195 let tx_frame = can::TxFrame::new(
196 can::TxFrameHeader {
197 len: 1,
198 frame_format: can::FrameFormat::Standard,
199 id: can::StandardId::new(0x123).unwrap().into(),
200 bit_rate_switching: false,
201 marker: None,
202 },
203 &[i],
204 )
205 .unwrap();
206
207 info!("Transmitting frame {}", i);
208 tx.write(&tx_frame).await;
209 }
210 for i in 3..max_buffered {
211 // Try filling up the RX FIFO0 buffers with extended packets
212 let tx_frame = can::TxFrame::new(
213 can::TxFrameHeader {
214 len: 1,
215 frame_format: can::FrameFormat::Standard,
216 id: can::ExtendedId::new(0x1232344).unwrap().into(),
217 bit_rate_switching: false,
218 marker: None,
219 },
220 &[i],
221 )
222 .unwrap();
223
224 info!("Transmitting frame {}", i);
225 tx.write(&tx_frame).await;
226 }
227
228 // Try and receive all 6 packets
229 for i in 0..max_buffered {
230 let envelope = rx.read().await.unwrap();
231 match envelope.header.id {
232 can::Id::Extended(id) => {
233 info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
234 }
235 can::Id::Standard(id) => {
236 info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
237 }
238 }
239 }
240
241 info!("Test OK");
242 cortex_m::asm::bkpt();
243}