aboutsummaryrefslogtreecommitdiff
path: root/tests/stm32/src/bin/fdcan.rs
diff options
context:
space:
mode:
authorCorey Schuhen <[email protected]>2024-03-27 19:43:19 +1000
committerCorey Schuhen <[email protected]>2024-03-28 09:32:13 +1000
commit8d43fb4da4712dd9bb5a2ae343168e536c2b3129 (patch)
tree6d0b3a434721a4be3482cf329983819b15b0ae4d /tests/stm32/src/bin/fdcan.rs
parent2217b802781b5f2188b4da659aca47f9d89ee032 (diff)
CAN: Use the same testing code for BXCAN and FDCAN h/w.
Diffstat (limited to 'tests/stm32/src/bin/fdcan.rs')
-rw-r--r--tests/stm32/src/bin/fdcan.rs195
1 files changed, 36 insertions, 159 deletions
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
index bddfa7684..27bdd038a 100644
--- a/tests/stm32/src/bin/fdcan.rs
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -6,13 +6,15 @@
6#[path = "../common.rs"] 6#[path = "../common.rs"]
7mod common; 7mod common;
8use common::*; 8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
11use embassy_stm32::peripherals::*; 10use embassy_stm32::peripherals::*;
12use embassy_stm32::{bind_interrupts, can, Config}; 11use embassy_stm32::{bind_interrupts, can, Config};
13use embassy_time::{Duration, Instant}; 12use embassy_time::Duration;
14use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
15 14
15mod can_common;
16use can_common::*;
17
16bind_interrupts!(struct Irqs2 { 18bind_interrupts!(struct Irqs2 {
17 FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>; 19 FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>;
18 FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>; 20 FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>;
@@ -22,14 +24,8 @@ bind_interrupts!(struct Irqs1 {
22 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>; 24 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
23}); 25});
24 26
25struct TestOptions {
26 config: Config,
27 max_latency: Duration,
28 second_fifo_working: bool,
29}
30
31#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))] 27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
32fn options() -> TestOptions { 28fn options() -> (Config, TestOptions) {
33 use embassy_stm32::rcc; 29 use embassy_stm32::rcc;
34 info!("H75 config"); 30 info!("H75 config");
35 let mut c = config(); 31 let mut c = config();
@@ -38,15 +34,17 @@ fn options() -> TestOptions {
38 mode: rcc::HseMode::Oscillator, 34 mode: rcc::HseMode::Oscillator,
39 }); 35 });
40 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 36 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
41 TestOptions { 37 (
42 config: c, 38 c,
43 max_latency: Duration::from_micros(1200), 39 TestOptions {
44 second_fifo_working: false, 40 max_latency: Duration::from_micros(1200),
45 } 41 max_buffered: 3,
42 },
43 )
46} 44}
47 45
48#[cfg(any(feature = "stm32h7a3zi"))] 46#[cfg(any(feature = "stm32h7a3zi"))]
49fn options() -> TestOptions { 47fn options() -> (Config, TestOptions) {
50 use embassy_stm32::rcc; 48 use embassy_stm32::rcc;
51 info!("H7a config"); 49 info!("H7a config");
52 let mut c = config(); 50 let mut c = config();
@@ -55,29 +53,33 @@ fn options() -> TestOptions {
55 mode: rcc::HseMode::Oscillator, 53 mode: rcc::HseMode::Oscillator,
56 }); 54 });
57 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 55 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
58 TestOptions { 56 (
59 config: c, 57 c,
60 max_latency: Duration::from_micros(1200), 58 TestOptions {
61 second_fifo_working: false, 59 max_latency: Duration::from_micros(1200),
62 } 60 max_buffered: 3,
61 },
62 )
63} 63}
64 64
65#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))] 65#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))]
66fn options() -> TestOptions { 66fn options() -> (Config, TestOptions) {
67 info!("G4 config"); 67 info!("G4 config");
68 TestOptions { 68 (
69 config: config(), 69 config(),
70 max_latency: Duration::from_micros(500), 70 TestOptions {
71 second_fifo_working: true, 71 max_latency: Duration::from_micros(500),
72 } 72 max_buffered: 6,
73 },
74 )
73} 75}
74 76
75#[embassy_executor::main] 77#[embassy_executor::main]
76async fn main(_spawner: Spawner) { 78async fn main(_spawner: Spawner) {
77 //let peripherals = embassy_stm32::init(config()); 79 //let peripherals = embassy_stm32::init(config());
78 80
79 let options = options(); 81 let (config, options) = options();
80 let peripherals = embassy_stm32::init(options.config); 82 let peripherals = embassy_stm32::init(config);
81 83
82 let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1); 84 let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1);
83 let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2); 85 let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2);
@@ -98,141 +100,16 @@ async fn main(_spawner: Spawner) {
98 let mut can = can.into_internal_loopback_mode(); 100 let mut can = can.into_internal_loopback_mode();
99 let mut can2 = can2.into_internal_loopback_mode(); 101 let mut can2 = can2.into_internal_loopback_mode();
100 102
101 info!("CAN Configured"); 103 run_can_tests(&mut can, &options).await;
104 run_can_tests(&mut can2, &options).await;
102 105
103 let mut i: u8 = 0; 106 info!("CAN Configured");
104 loop {
105 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
106
107 info!("Transmitting frame...");
108 let tx_ts = Instant::now();
109 can.write(&tx_frame).await;
110
111 let (frame, timestamp) = can.read().await.unwrap().parts();
112 info!("Frame received!");
113
114 // Check data.
115 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
116
117 info!("loopback time {}", timestamp);
118 info!("loopback frame {=u8}", frame.data()[0]);
119 let latency = timestamp.saturating_duration_since(tx_ts);
120 info!("loopback latency {} us", latency.as_micros());
121
122 // Theoretical minimum latency is 55us, actual is usually ~80us
123 const MIN_LATENCY: Duration = Duration::from_micros(50);
124 // Was failing at 150 but we are not getting a real time stamp. I'm not
125 // sure if there are other delays
126 assert!(
127 MIN_LATENCY <= latency && latency <= options.max_latency,
128 "{} <= {} <= {}",
129 MIN_LATENCY,
130 latency,
131 options.max_latency
132 );
133
134 i += 1;
135 if i > 10 {
136 break;
137 }
138 }
139
140 let mut i: u8 = 0;
141 loop {
142 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
143
144 info!("Transmitting frame...");
145 let tx_ts = Instant::now();
146 can2.write(&tx_frame).await;
147
148 let (frame, timestamp) = can2.read().await.unwrap().parts();
149 info!("Frame received!");
150
151 //print_regs().await;
152 // Check data.
153 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
154
155 info!("loopback time {}", timestamp);
156 info!("loopback frame {=u8}", frame.data()[0]);
157 let latency = timestamp.saturating_duration_since(tx_ts);
158 info!("loopback latency {} us", latency.as_micros());
159
160 // Theoretical minimum latency is 55us, actual is usually ~80us
161 const MIN_LATENCY: Duration = Duration::from_micros(50);
162 // Was failing at 150 but we are not getting a real time stamp. I'm not
163 // sure if there are other delays
164 assert!(
165 MIN_LATENCY <= latency && latency <= options.max_latency,
166 "{} <= {} <= {}",
167 MIN_LATENCY,
168 latency,
169 options.max_latency
170 );
171
172 i += 1;
173 if i > 10 {
174 break;
175 }
176 }
177
178 let max_buffered = if options.second_fifo_working { 6 } else { 3 };
179
180 // Below here, check that we can receive from both FIFO0 and FIFO0
181 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
182 // in each FIFO so make sure we write enough to fill them both up before reading.
183 for i in 0..3 {
184 // Try filling up the RX FIFO0 buffers with standard packets
185 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
186 info!("Transmitting frame {}", i);
187 can.write(&tx_frame).await;
188 }
189 for i in 3..max_buffered {
190 // Try filling up the RX FIFO0 buffers with extended packets
191 let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap();
192 info!("Transmitting frame {}", i);
193 can.write(&tx_frame).await;
194 }
195
196 // Try and receive all 6 packets
197 for i in 0..max_buffered {
198 let (frame, _ts) = can.read().await.unwrap().parts();
199 match frame.id() {
200 embedded_can::Id::Extended(id) => {
201 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
202 }
203 embedded_can::Id::Standard(id) => {
204 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
205 }
206 }
207 }
208 107
209 // Test again with a split 108 // Test again with a split
210 let (mut tx, mut rx) = can.split(); 109 let (mut tx, mut rx) = can.split();
211 for i in 0..3 { 110 let (mut tx2, mut rx2) = can2.split();
212 // Try filling up the RX FIFO0 buffers with standard packets 111 run_split_can_tests(&mut tx, &mut rx, &options).await;
213 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); 112 run_split_can_tests(&mut tx2, &mut rx2, &options).await;
214 info!("Transmitting frame {}", i);
215 tx.write(&tx_frame).await;
216 }
217 for i in 3..max_buffered {
218 // Try filling up the RX FIFO0 buffers with extended packets
219 let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap();
220 info!("Transmitting frame {}", i);
221 tx.write(&tx_frame).await;
222 }
223
224 // Try and receive all 6 packets
225 for i in 0..max_buffered {
226 let (frame, _ts) = rx.read().await.unwrap().parts();
227 match frame.id() {
228 embedded_can::Id::Extended(id) => {
229 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
230 }
231 embedded_can::Id::Standard(id) => {
232 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
233 }
234 }
235 }
236 113
237 info!("Test OK"); 114 info!("Test OK");
238 cortex_m::asm::bkpt(); 115 cortex_m::asm::bkpt();