diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/rp/src/bin/gpio_multicore.rs | 12 | ||||
| -rw-r--r-- | tests/rp/src/bin/i2c.rs | 12 | ||||
| -rw-r--r-- | tests/rp/src/bin/multicore.rs | 12 | ||||
| -rw-r--r-- | tests/rp/src/bin/pwm.rs | 14 | ||||
| -rw-r--r-- | tests/stm32/Cargo.toml | 8 | ||||
| -rw-r--r-- | tests/stm32/src/bin/can.rs | 67 | ||||
| -rw-r--r-- | tests/stm32/src/bin/can_common.rs | 112 | ||||
| -rw-r--r-- | tests/stm32/src/bin/cryp.rs | 30 | ||||
| -rw-r--r-- | tests/stm32/src/bin/fdcan.rs | 172 | ||||
| -rw-r--r-- | tests/stm32/src/bin/ucpd.rs | 120 | ||||
| -rw-r--r-- | tests/stm32/src/common.rs | 8 |
11 files changed, 363 insertions, 204 deletions
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs index 8aed9b80c..e9c6f3122 100644 --- a/tests/rp/src/bin/gpio_multicore.rs +++ b/tests/rp/src/bin/gpio_multicore.rs | |||
| @@ -21,10 +21,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = Channel::new(); | |||
| 21 | #[cortex_m_rt::entry] | 21 | #[cortex_m_rt::entry] |
| 22 | fn main() -> ! { | 22 | fn main() -> ! { |
| 23 | let p = embassy_rp::init(Default::default()); | 23 | let p = embassy_rp::init(Default::default()); |
| 24 | spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { | 24 | spawn_core1( |
| 25 | let executor1 = EXECUTOR1.init(Executor::new()); | 25 | p.CORE1, |
| 26 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); | 26 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, |
| 27 | }); | 27 | move || { |
| 28 | let executor1 = EXECUTOR1.init(Executor::new()); | ||
| 29 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); | ||
| 30 | }, | ||
| 31 | ); | ||
| 28 | let executor0 = EXECUTOR0.init(Executor::new()); | 32 | let executor0 = EXECUTOR0.init(Executor::new()); |
| 29 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); | 33 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); |
| 30 | } | 34 | } |
diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs index 153b37999..9615007bd 100644 --- a/tests/rp/src/bin/i2c.rs +++ b/tests/rp/src/bin/i2c.rs | |||
| @@ -210,10 +210,14 @@ async fn controller_task(con: &mut i2c::I2c<'static, I2C0, i2c::Async>) { | |||
| 210 | config.addr = DEV_ADDR as u16; | 210 | config.addr = DEV_ADDR as u16; |
| 211 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); | 211 | let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); |
| 212 | 212 | ||
| 213 | spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { | 213 | spawn_core1( |
| 214 | let executor1 = EXECUTOR1.init(Executor::new()); | 214 | p.CORE1, |
| 215 | executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); | 215 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, |
| 216 | }); | 216 | move || { |
| 217 | let executor1 = EXECUTOR1.init(Executor::new()); | ||
| 218 | executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); | ||
| 219 | }, | ||
| 220 | ); | ||
| 217 | 221 | ||
| 218 | let c_sda = p.PIN_21; | 222 | let c_sda = p.PIN_21; |
| 219 | let c_scl = p.PIN_20; | 223 | let c_scl = p.PIN_20; |
diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs index 60d9f85ec..783ea0f27 100644 --- a/tests/rp/src/bin/multicore.rs +++ b/tests/rp/src/bin/multicore.rs | |||
| @@ -19,10 +19,14 @@ static CHANNEL1: Channel<CriticalSectionRawMutex, bool, 1> = Channel::new(); | |||
| 19 | #[cortex_m_rt::entry] | 19 | #[cortex_m_rt::entry] |
| 20 | fn main() -> ! { | 20 | fn main() -> ! { |
| 21 | let p = embassy_rp::init(Default::default()); | 21 | let p = embassy_rp::init(Default::default()); |
| 22 | spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { | 22 | spawn_core1( |
| 23 | let executor1 = EXECUTOR1.init(Executor::new()); | 23 | p.CORE1, |
| 24 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); | 24 | unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, |
| 25 | }); | 25 | move || { |
| 26 | let executor1 = EXECUTOR1.init(Executor::new()); | ||
| 27 | executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); | ||
| 28 | }, | ||
| 29 | ); | ||
| 26 | let executor0 = EXECUTOR0.init(Executor::new()); | 30 | let executor0 = EXECUTOR0.init(Executor::new()); |
| 27 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); | 31 | executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); |
| 28 | } | 32 | } |
diff --git a/tests/rp/src/bin/pwm.rs b/tests/rp/src/bin/pwm.rs index e71d9e610..4b02e5bab 100644 --- a/tests/rp/src/bin/pwm.rs +++ b/tests/rp/src/bin/pwm.rs | |||
| @@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) { | |||
| 28 | 28 | ||
| 29 | // Test free-running clock | 29 | // Test free-running clock |
| 30 | { | 30 | { |
| 31 | let pwm = Pwm::new_free(&mut p.PWM_CH3, cfg.clone()); | 31 | let pwm = Pwm::new_free(&mut p.PWM_SLICE3, cfg.clone()); |
| 32 | cortex_m::asm::delay(125); | 32 | cortex_m::asm::delay(125); |
| 33 | let ctr = pwm.counter(); | 33 | let ctr = pwm.counter(); |
| 34 | assert!(ctr > 0); | 34 | assert!(ctr > 0); |
| @@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) { | |||
| 46 | // Test output from A | 46 | // Test output from A |
| 47 | { | 47 | { |
| 48 | let pin1 = Input::new(&mut p9, Pull::None); | 48 | let pin1 = Input::new(&mut p9, Pull::None); |
| 49 | let _pwm = Pwm::new_output_a(&mut p.PWM_CH3, &mut p6, cfg.clone()); | 49 | let _pwm = Pwm::new_output_a(&mut p.PWM_SLICE3, &mut p6, cfg.clone()); |
| 50 | Timer::after_millis(1).await; | 50 | Timer::after_millis(1).await; |
| 51 | assert_eq!(pin1.is_low(), invert_a); | 51 | assert_eq!(pin1.is_low(), invert_a); |
| 52 | Timer::after_millis(5).await; | 52 | Timer::after_millis(5).await; |
| @@ -60,7 +60,7 @@ async fn main(_spawner: Spawner) { | |||
| 60 | // Test output from B | 60 | // Test output from B |
| 61 | { | 61 | { |
| 62 | let pin2 = Input::new(&mut p11, Pull::None); | 62 | let pin2 = Input::new(&mut p11, Pull::None); |
| 63 | let _pwm = Pwm::new_output_b(&mut p.PWM_CH3, &mut p7, cfg.clone()); | 63 | let _pwm = Pwm::new_output_b(&mut p.PWM_SLICE3, &mut p7, cfg.clone()); |
| 64 | Timer::after_millis(1).await; | 64 | Timer::after_millis(1).await; |
| 65 | assert_ne!(pin2.is_low(), invert_a); | 65 | assert_ne!(pin2.is_low(), invert_a); |
| 66 | Timer::after_millis(5).await; | 66 | Timer::after_millis(5).await; |
| @@ -75,7 +75,7 @@ async fn main(_spawner: Spawner) { | |||
| 75 | { | 75 | { |
| 76 | let pin1 = Input::new(&mut p9, Pull::None); | 76 | let pin1 = Input::new(&mut p9, Pull::None); |
| 77 | let pin2 = Input::new(&mut p11, Pull::None); | 77 | let pin2 = Input::new(&mut p11, Pull::None); |
| 78 | let _pwm = Pwm::new_output_ab(&mut p.PWM_CH3, &mut p6, &mut p7, cfg.clone()); | 78 | let _pwm = Pwm::new_output_ab(&mut p.PWM_SLICE3, &mut p6, &mut p7, cfg.clone()); |
| 79 | Timer::after_millis(1).await; | 79 | Timer::after_millis(1).await; |
| 80 | assert_eq!(pin1.is_low(), invert_a); | 80 | assert_eq!(pin1.is_low(), invert_a); |
| 81 | assert_ne!(pin2.is_low(), invert_a); | 81 | assert_ne!(pin2.is_low(), invert_a); |
| @@ -94,7 +94,7 @@ async fn main(_spawner: Spawner) { | |||
| 94 | // Test level-gated | 94 | // Test level-gated |
| 95 | { | 95 | { |
| 96 | let mut pin2 = Output::new(&mut p11, Level::Low); | 96 | let mut pin2 = Output::new(&mut p11, Level::Low); |
| 97 | let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::Level, cfg.clone()); | 97 | let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::Level, cfg.clone()); |
| 98 | assert_eq!(pwm.counter(), 0); | 98 | assert_eq!(pwm.counter(), 0); |
| 99 | Timer::after_millis(5).await; | 99 | Timer::after_millis(5).await; |
| 100 | assert_eq!(pwm.counter(), 0); | 100 | assert_eq!(pwm.counter(), 0); |
| @@ -110,7 +110,7 @@ async fn main(_spawner: Spawner) { | |||
| 110 | // Test rising-gated | 110 | // Test rising-gated |
| 111 | { | 111 | { |
| 112 | let mut pin2 = Output::new(&mut p11, Level::Low); | 112 | let mut pin2 = Output::new(&mut p11, Level::Low); |
| 113 | let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::RisingEdge, cfg.clone()); | 113 | let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::RisingEdge, cfg.clone()); |
| 114 | assert_eq!(pwm.counter(), 0); | 114 | assert_eq!(pwm.counter(), 0); |
| 115 | Timer::after_millis(5).await; | 115 | Timer::after_millis(5).await; |
| 116 | assert_eq!(pwm.counter(), 0); | 116 | assert_eq!(pwm.counter(), 0); |
| @@ -125,7 +125,7 @@ async fn main(_spawner: Spawner) { | |||
| 125 | // Test falling-gated | 125 | // Test falling-gated |
| 126 | { | 126 | { |
| 127 | let mut pin2 = Output::new(&mut p11, Level::High); | 127 | let mut pin2 = Output::new(&mut p11, Level::High); |
| 128 | let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::FallingEdge, cfg.clone()); | 128 | let pwm = Pwm::new_input(&mut p.PWM_SLICE3, &mut p7, InputMode::FallingEdge, cfg.clone()); |
| 129 | assert_eq!(pwm.counter(), 0); | 129 | assert_eq!(pwm.counter(), 0); |
| 130 | Timer::after_millis(5).await; | 130 | Timer::after_millis(5).await; |
| 131 | assert_eq!(pwm.counter(), 0); | 131 | assert_eq!(pwm.counter(), 0); |
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index bfe003a11..e42470004 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml | |||
| @@ -13,7 +13,7 @@ stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] | |||
| 13 | stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"] | 13 | stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"] |
| 14 | stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"] | 14 | stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"] |
| 15 | stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] | 15 | stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] |
| 16 | stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"] | 16 | stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"] |
| 17 | stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"] | 17 | stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"] |
| 18 | stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"] | 18 | stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"] |
| 19 | stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] | 19 | stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] |
| @@ -47,6 +47,7 @@ mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] | |||
| 47 | embassy-stm32-wpan = [] | 47 | embassy-stm32-wpan = [] |
| 48 | not-gpdma = [] | 48 | not-gpdma = [] |
| 49 | dac = [] | 49 | dac = [] |
| 50 | ucpd = [] | ||
| 50 | 51 | ||
| 51 | cm0 = ["portable-atomic/unsafe-assume-single-core"] | 52 | cm0 = ["portable-atomic/unsafe-assume-single-core"] |
| 52 | 53 | ||
| @@ -161,6 +162,11 @@ path = "src/bin/timer.rs" | |||
| 161 | required-features = [] | 162 | required-features = [] |
| 162 | 163 | ||
| 163 | [[bin]] | 164 | [[bin]] |
| 165 | name = "ucpd" | ||
| 166 | path = "src/bin/ucpd.rs" | ||
| 167 | required-features = [ "ucpd",] | ||
| 168 | |||
| 169 | [[bin]] | ||
| 164 | name = "usart" | 170 | name = "usart" |
| 165 | path = "src/bin/usart.rs" | 171 | path = "src/bin/usart.rs" |
| 166 | required-features = [] | 172 | required-features = [] |
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index f4effa244..551764458 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs | |||
| @@ -6,17 +6,20 @@ | |||
| 6 | #[path = "../common.rs"] | 6 | #[path = "../common.rs"] |
| 7 | mod common; | 7 | mod common; |
| 8 | use common::*; | 8 | use common::*; |
| 9 | use defmt::assert; | ||
| 10 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::bind_interrupts; | 10 | use embassy_stm32::bind_interrupts; |
| 12 | use embassy_stm32::can::bxcan::filter::Mask32; | 11 | use embassy_stm32::can::filter::Mask32; |
| 13 | use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; | 12 | use embassy_stm32::can::{ |
| 14 | use embassy_stm32::can::{Can, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; | 13 | Can, Fifo, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, |
| 14 | }; | ||
| 15 | use embassy_stm32::gpio::{Input, Pull}; | 15 | use embassy_stm32::gpio::{Input, Pull}; |
| 16 | use embassy_stm32::peripherals::CAN1; | 16 | use embassy_stm32::peripherals::CAN1; |
| 17 | use embassy_time::{Duration, Instant}; | 17 | use embassy_time::Duration; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 19 | 19 | ||
| 20 | mod can_common; | ||
| 21 | use can_common::*; | ||
| 22 | |||
| 20 | bind_interrupts!(struct Irqs { | 23 | bind_interrupts!(struct Irqs { |
| 21 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; | 24 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; |
| 22 | CAN1_RX1 => Rx1InterruptHandler<CAN1>; | 25 | CAN1_RX1 => Rx1InterruptHandler<CAN1>; |
| @@ -29,6 +32,11 @@ async fn main(_spawner: Spawner) { | |||
| 29 | let p = embassy_stm32::init(config()); | 32 | let p = embassy_stm32::init(config()); |
| 30 | info!("Hello World!"); | 33 | info!("Hello World!"); |
| 31 | 34 | ||
| 35 | let options = TestOptions { | ||
| 36 | max_latency: Duration::from_micros(1200), | ||
| 37 | max_buffered: 2, | ||
| 38 | }; | ||
| 39 | |||
| 32 | let can = peri!(p, CAN); | 40 | let can = peri!(p, CAN); |
| 33 | let tx = peri!(p, CAN_TX); | 41 | let tx = peri!(p, CAN_TX); |
| 34 | let mut rx = peri!(p, CAN_RX); | 42 | let mut rx = peri!(p, CAN_RX); |
| @@ -44,54 +52,25 @@ async fn main(_spawner: Spawner) { | |||
| 44 | 52 | ||
| 45 | info!("Configuring can..."); | 53 | info!("Configuring can..."); |
| 46 | 54 | ||
| 47 | can.as_mut() | 55 | can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); |
| 48 | .modify_filters() | ||
| 49 | .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | ||
| 50 | 56 | ||
| 51 | can.set_bitrate(1_000_000); | 57 | can.modify_config() |
| 52 | can.as_mut() | ||
| 53 | .modify_config() | ||
| 54 | .set_loopback(true) // Receive own frames | 58 | .set_loopback(true) // Receive own frames |
| 55 | .set_silent(true) | 59 | .set_silent(true) |
| 56 | // .set_bit_timing(0x001c0003) | 60 | // .set_bit_timing(0x001c0003) |
| 57 | .enable(); | 61 | .set_bitrate(1_000_000); |
| 58 | |||
| 59 | info!("Can configured"); | ||
| 60 | |||
| 61 | let mut i: u8 = 0; | ||
| 62 | loop { | ||
| 63 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), [i]); | ||
| 64 | 62 | ||
| 65 | info!("Transmitting frame..."); | 63 | can.enable().await; |
| 66 | let tx_ts = Instant::now(); | ||
| 67 | can.write(&tx_frame).await; | ||
| 68 | 64 | ||
| 69 | let envelope = can.read().await.unwrap(); | 65 | info!("Can configured"); |
| 70 | info!("Frame received!"); | ||
| 71 | |||
| 72 | info!("loopback time {}", envelope.ts); | ||
| 73 | info!("loopback frame {=u8}", envelope.frame.data().unwrap()[0]); | ||
| 74 | |||
| 75 | let latency = envelope.ts.saturating_duration_since(tx_ts); | ||
| 76 | info!("loopback latency {} us", latency.as_micros()); | ||
| 77 | 66 | ||
| 78 | // Theoretical minimum latency is 55us, actual is usually ~80us | 67 | run_can_tests(&mut can, &options).await; |
| 79 | const MIN_LATENCY: Duration = Duration::from_micros(50); | ||
| 80 | const MAX_LATENCY: Duration = Duration::from_micros(150); | ||
| 81 | assert!( | ||
| 82 | MIN_LATENCY <= latency && latency <= MAX_LATENCY, | ||
| 83 | "{} <= {} <= {}", | ||
| 84 | MIN_LATENCY, | ||
| 85 | latency, | ||
| 86 | MAX_LATENCY | ||
| 87 | ); | ||
| 88 | 68 | ||
| 89 | i += 1; | 69 | // Test again with a split |
| 90 | if i > 10 { | 70 | let (mut tx, mut rx) = can.split(); |
| 91 | break; | 71 | run_split_can_tests(&mut tx, &mut rx, &options).await; |
| 92 | } | ||
| 93 | } | ||
| 94 | 72 | ||
| 95 | info!("Test OK"); | 73 | info!("Test OK"); |
| 74 | |||
| 96 | cortex_m::asm::bkpt(); | 75 | cortex_m::asm::bkpt(); |
| 97 | } | 76 | } |
diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs new file mode 100644 index 000000000..4b39269cc --- /dev/null +++ b/tests/stm32/src/bin/can_common.rs | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | use defmt::{assert, *}; | ||
| 2 | use embassy_stm32::can; | ||
| 3 | use embassy_time::{Duration, Instant}; | ||
| 4 | |||
| 5 | #[derive(Clone, Copy, Debug)] | ||
| 6 | pub struct TestOptions { | ||
| 7 | pub max_latency: Duration, | ||
| 8 | pub max_buffered: u8, | ||
| 9 | } | ||
| 10 | |||
| 11 | pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { | ||
| 12 | let mut i: u8 = 0; | ||
| 13 | loop { | ||
| 14 | //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap(); | ||
| 15 | let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); | ||
| 16 | |||
| 17 | //info!("Transmitting frame..."); | ||
| 18 | let tx_ts = Instant::now(); | ||
| 19 | can.write(&tx_frame).await; | ||
| 20 | |||
| 21 | let (frame, timestamp) = can.read().await.unwrap().parts(); | ||
| 22 | //info!("Frame received!"); | ||
| 23 | |||
| 24 | // Check data. | ||
| 25 | assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]); | ||
| 26 | |||
| 27 | //info!("loopback time {}", timestamp); | ||
| 28 | //info!("loopback frame {=u8}", frame.data()[0]); | ||
| 29 | let latency = timestamp.saturating_duration_since(tx_ts); | ||
| 30 | info!("loopback latency {} us", latency.as_micros()); | ||
| 31 | |||
| 32 | // Theoretical minimum latency is 55us, actual is usually ~80us | ||
| 33 | const MIN_LATENCY: Duration = Duration::from_micros(50); | ||
| 34 | // Was failing at 150 but we are not getting a real time stamp. I'm not | ||
| 35 | // sure if there are other delays | ||
| 36 | assert!( | ||
| 37 | MIN_LATENCY <= latency && latency <= options.max_latency, | ||
| 38 | "{} <= {} <= {}", | ||
| 39 | MIN_LATENCY, | ||
| 40 | latency, | ||
| 41 | options.max_latency | ||
| 42 | ); | ||
| 43 | |||
| 44 | i += 1; | ||
| 45 | if i > 5 { | ||
| 46 | break; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | // Below here, check that we can receive from both FIFO0 and FIFO1 | ||
| 51 | // Above we configured FIFO1 for extended ID packets. There are only 3 slots | ||
| 52 | // in each FIFO so make sure we write enough to fill them both up before reading. | ||
| 53 | for i in 0..options.max_buffered { | ||
| 54 | // Try filling up the RX FIFO0 buffers | ||
| 55 | //let tx_frame = if 0 != (i & 0x01) { | ||
| 56 | let tx_frame = if i < options.max_buffered / 2 { | ||
| 57 | info!("Transmitting standard frame {}", i); | ||
| 58 | can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() | ||
| 59 | } else { | ||
| 60 | info!("Transmitting extended frame {}", i); | ||
| 61 | can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() | ||
| 62 | }; | ||
| 63 | can.write(&tx_frame).await; | ||
| 64 | } | ||
| 65 | |||
| 66 | // Try and receive all 6 packets | ||
| 67 | for _i in 0..options.max_buffered { | ||
| 68 | let (frame, _ts) = can.read().await.unwrap().parts(); | ||
| 69 | match frame.id() { | ||
| 70 | embedded_can::Id::Extended(_id) => { | ||
| 71 | info!("Extended received! {}", frame.data()[0]); | ||
| 72 | //info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 73 | } | ||
| 74 | embedded_can::Id::Standard(_id) => { | ||
| 75 | info!("Standard received! {}", frame.data()[0]); | ||
| 76 | //info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | pub async fn run_split_can_tests<'d, T: can::Instance>( | ||
| 83 | tx: &mut can::CanTx<'d, T>, | ||
| 84 | rx: &mut can::CanRx<'d, T>, | ||
| 85 | options: &TestOptions, | ||
| 86 | ) { | ||
| 87 | for i in 0..options.max_buffered { | ||
| 88 | // Try filling up the RX FIFO0 buffers | ||
| 89 | //let tx_frame = if 0 != (i & 0x01) { | ||
| 90 | let tx_frame = if i < options.max_buffered / 2 { | ||
| 91 | info!("Transmitting standard frame {}", i); | ||
| 92 | can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap() | ||
| 93 | } else { | ||
| 94 | info!("Transmitting extended frame {}", i); | ||
| 95 | can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap() | ||
| 96 | }; | ||
| 97 | tx.write(&tx_frame).await; | ||
| 98 | } | ||
| 99 | |||
| 100 | // Try and receive all 6 packets | ||
| 101 | for _i in 0..options.max_buffered { | ||
| 102 | let (frame, _ts) = rx.read().await.unwrap().parts(); | ||
| 103 | match frame.id() { | ||
| 104 | embedded_can::Id::Extended(_id) => { | ||
| 105 | info!("Extended received! {}", frame.data()[0]); | ||
| 106 | } | ||
| 107 | embedded_can::Id::Standard(_id) => { | ||
| 108 | info!("Standard received! {}", frame.data()[0]); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
diff --git a/tests/stm32/src/bin/cryp.rs b/tests/stm32/src/bin/cryp.rs index f105abf26..60778bdaa 100644 --- a/tests/stm32/src/bin/cryp.rs +++ b/tests/stm32/src/bin/cryp.rs | |||
| @@ -10,9 +10,14 @@ use aes_gcm::aead::{AeadInPlace, KeyInit}; | |||
| 10 | use aes_gcm::Aes128Gcm; | 10 | use aes_gcm::Aes128Gcm; |
| 11 | use common::*; | 11 | use common::*; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::cryp::*; | 13 | use embassy_stm32::cryp::{self, *}; |
| 14 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | CRYP => cryp::InterruptHandler<peripherals::CRYP>; | ||
| 19 | }); | ||
| 20 | |||
| 16 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 22 | async fn main(_spawner: Spawner) { |
| 18 | let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); | 23 | let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); |
| @@ -22,27 +27,32 @@ async fn main(_spawner: Spawner) { | |||
| 22 | const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1"; | 27 | const AAD1: &[u8] = b"additional data 1 stdargadrhaethaethjatjatjaetjartjstrjsfkk;'jopofyuisrteytweTASTUIKFUKIXTRDTEREharhaeryhaterjartjarthaethjrtjarthaetrhartjatejatrjsrtjartjyt1"; |
| 23 | const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg"; | 28 | const AAD2: &[u8] = b"additional data 2 stdhthsthsthsrthsrthsrtjdykjdukdyuldadfhsdghsdghsdghsadghjk'hioethjrtjarthaetrhartjatecfgjhzdfhgzdfhzdfghzdfhzdfhzfhjatrjsrtjartjytjfytjfyg"; |
| 24 | 29 | ||
| 25 | let hw_cryp = Cryp::new(p.CRYP); | 30 | let in_dma = peri!(p, CRYP_IN_DMA); |
| 31 | let out_dma = peri!(p, CRYP_OUT_DMA); | ||
| 32 | |||
| 33 | let mut hw_cryp = Cryp::new(p.CRYP, in_dma, out_dma, Irqs); | ||
| 26 | let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; | 34 | let key: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; |
| 27 | let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; | 35 | let mut ciphertext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; |
| 28 | let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; | 36 | let mut plaintext: [u8; PAYLOAD1.len() + PAYLOAD2.len()] = [0; PAYLOAD1.len() + PAYLOAD2.len()]; |
| 29 | let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; | 37 | let iv: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; |
| 30 | 38 | ||
| 31 | // Encrypt in hardware using AES-GCM 128-bit | 39 | // Encrypt in hardware using AES-GCM 128-bit in blocking mode. |
| 32 | let aes_gcm = AesGcm::new(&key, &iv); | 40 | let aes_gcm = AesGcm::new(&key, &iv); |
| 33 | let mut gcm_encrypt = hw_cryp.start(&aes_gcm, Direction::Encrypt); | 41 | let mut gcm_encrypt = hw_cryp.start_blocking(&aes_gcm, Direction::Encrypt); |
| 34 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false); | 42 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD1, false); |
| 35 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true); | 43 | hw_cryp.aad_blocking(&mut gcm_encrypt, AAD2, true); |
| 36 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false); | 44 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD1, &mut ciphertext[..PAYLOAD1.len()], false); |
| 37 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true); | 45 | hw_cryp.payload_blocking(&mut gcm_encrypt, PAYLOAD2, &mut ciphertext[PAYLOAD1.len()..], true); |
| 38 | let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); | 46 | let encrypt_tag = hw_cryp.finish_blocking(gcm_encrypt); |
| 39 | 47 | ||
| 40 | // Decrypt in hardware using AES-GCM 128-bit | 48 | // Decrypt in hardware using AES-GCM 128-bit in async (DMA) mode. |
| 41 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt); | 49 | let mut gcm_decrypt = hw_cryp.start(&aes_gcm, Direction::Decrypt).await; |
| 42 | hw_cryp.aad_blocking(&mut gcm_decrypt, AAD1, false); | 50 | hw_cryp.aad(&mut gcm_decrypt, AAD1, false).await; |
| 43 | hw_cryp.aad_blocking(&mut gcm_decrypt, AAD2, true); | 51 | hw_cryp.aad(&mut gcm_decrypt, AAD2, true).await; |
| 44 | hw_cryp.payload_blocking(&mut gcm_decrypt, &ciphertext, &mut plaintext, true); | 52 | hw_cryp |
| 45 | let decrypt_tag = hw_cryp.finish_blocking(gcm_decrypt); | 53 | .payload(&mut gcm_decrypt, &ciphertext, &mut plaintext, true) |
| 54 | .await; | ||
| 55 | let decrypt_tag = hw_cryp.finish(gcm_decrypt).await; | ||
| 46 | 56 | ||
| 47 | info!("AES-GCM Ciphertext: {:?}", ciphertext); | 57 | info!("AES-GCM Ciphertext: {:?}", ciphertext); |
| 48 | info!("AES-GCM Plaintext: {:?}", plaintext); | 58 | info!("AES-GCM Plaintext: {:?}", plaintext); |
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs index dd78d7fb3..27bdd038a 100644 --- a/tests/stm32/src/bin/fdcan.rs +++ b/tests/stm32/src/bin/fdcan.rs | |||
| @@ -6,26 +6,26 @@ | |||
| 6 | #[path = "../common.rs"] | 6 | #[path = "../common.rs"] |
| 7 | mod common; | 7 | mod common; |
| 8 | use common::*; | 8 | use common::*; |
| 9 | use defmt::assert; | ||
| 10 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::peripherals::*; | 10 | use embassy_stm32::peripherals::*; |
| 12 | use embassy_stm32::{bind_interrupts, can, Config}; | 11 | use embassy_stm32::{bind_interrupts, can, Config}; |
| 13 | use embassy_time::{Duration, Instant}; | 12 | use embassy_time::Duration; |
| 14 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 14 | ||
| 16 | bind_interrupts!(struct Irqs { | 15 | mod can_common; |
| 16 | use can_common::*; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs2 { | ||
| 19 | FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>; | ||
| 20 | FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>; | ||
| 21 | }); | ||
| 22 | bind_interrupts!(struct Irqs1 { | ||
| 17 | FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>; | 23 | FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>; |
| 18 | FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>; | 24 | FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>; |
| 19 | }); | 25 | }); |
| 20 | 26 | ||
| 21 | struct TestOptions { | ||
| 22 | config: Config, | ||
| 23 | max_latency: Duration, | ||
| 24 | second_fifo_working: bool, | ||
| 25 | } | ||
| 26 | |||
| 27 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))] | 27 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))] |
| 28 | fn options() -> TestOptions { | 28 | fn options() -> (Config, TestOptions) { |
| 29 | use embassy_stm32::rcc; | 29 | use embassy_stm32::rcc; |
| 30 | info!("H75 config"); | 30 | info!("H75 config"); |
| 31 | let mut c = config(); | 31 | let mut c = config(); |
| @@ -34,15 +34,17 @@ fn options() -> TestOptions { | |||
| 34 | mode: rcc::HseMode::Oscillator, | 34 | mode: rcc::HseMode::Oscillator, |
| 35 | }); | 35 | }); |
| 36 | c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; | 36 | c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; |
| 37 | TestOptions { | 37 | ( |
| 38 | config: c, | 38 | c, |
| 39 | max_latency: Duration::from_micros(1200), | 39 | TestOptions { |
| 40 | second_fifo_working: false, | 40 | max_latency: Duration::from_micros(1200), |
| 41 | } | 41 | max_buffered: 3, |
| 42 | }, | ||
| 43 | ) | ||
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | #[cfg(any(feature = "stm32h7a3zi"))] | 46 | #[cfg(any(feature = "stm32h7a3zi"))] |
| 45 | fn options() -> TestOptions { | 47 | fn options() -> (Config, TestOptions) { |
| 46 | use embassy_stm32::rcc; | 48 | use embassy_stm32::rcc; |
| 47 | info!("H7a config"); | 49 | info!("H7a config"); |
| 48 | let mut c = config(); | 50 | let mut c = config(); |
| @@ -51,139 +53,63 @@ fn options() -> TestOptions { | |||
| 51 | mode: rcc::HseMode::Oscillator, | 53 | mode: rcc::HseMode::Oscillator, |
| 52 | }); | 54 | }); |
| 53 | c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; | 55 | c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; |
| 54 | TestOptions { | 56 | ( |
| 55 | config: c, | 57 | c, |
| 56 | max_latency: Duration::from_micros(1200), | 58 | TestOptions { |
| 57 | second_fifo_working: false, | 59 | max_latency: Duration::from_micros(1200), |
| 58 | } | 60 | max_buffered: 3, |
| 61 | }, | ||
| 62 | ) | ||
| 59 | } | 63 | } |
| 60 | 64 | ||
| 61 | #[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))] | 65 | #[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))] |
| 62 | fn options() -> TestOptions { | 66 | fn options() -> (Config, TestOptions) { |
| 63 | info!("G4 config"); | 67 | info!("G4 config"); |
| 64 | TestOptions { | 68 | ( |
| 65 | config: config(), | 69 | config(), |
| 66 | max_latency: Duration::from_micros(500), | 70 | TestOptions { |
| 67 | second_fifo_working: true, | 71 | max_latency: Duration::from_micros(500), |
| 68 | } | 72 | max_buffered: 6, |
| 73 | }, | ||
| 74 | ) | ||
| 69 | } | 75 | } |
| 70 | 76 | ||
| 71 | #[embassy_executor::main] | 77 | #[embassy_executor::main] |
| 72 | async fn main(_spawner: Spawner) { | 78 | async fn main(_spawner: Spawner) { |
| 73 | //let peripherals = embassy_stm32::init(config()); | 79 | //let peripherals = embassy_stm32::init(config()); |
| 74 | 80 | ||
| 75 | let options = options(); | 81 | let (config, options) = options(); |
| 76 | let peripherals = embassy_stm32::init(options.config); | 82 | let peripherals = embassy_stm32::init(config); |
| 77 | 83 | ||
| 78 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); | 84 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1); |
| 85 | let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2); | ||
| 79 | 86 | ||
| 80 | // 250k bps | 87 | // 250k bps |
| 81 | can.set_bitrate(250_000); | 88 | can.set_bitrate(250_000); |
| 89 | can2.set_bitrate(250_000); | ||
| 82 | 90 | ||
| 83 | can.set_extended_filter( | 91 | can.set_extended_filter( |
| 84 | can::filter::ExtendedFilterSlot::_0, | 92 | can::filter::ExtendedFilterSlot::_0, |
| 85 | can::filter::ExtendedFilter::accept_all_into_fifo1(), | 93 | can::filter::ExtendedFilter::accept_all_into_fifo1(), |
| 86 | ); | 94 | ); |
| 95 | can2.set_extended_filter( | ||
| 96 | can::filter::ExtendedFilterSlot::_0, | ||
| 97 | can::filter::ExtendedFilter::accept_all_into_fifo1(), | ||
| 98 | ); | ||
| 87 | 99 | ||
| 88 | let mut can = can.into_internal_loopback_mode(); | 100 | let mut can = can.into_internal_loopback_mode(); |
| 101 | let mut can2 = can2.into_internal_loopback_mode(); | ||
| 89 | 102 | ||
| 90 | info!("CAN Configured"); | 103 | run_can_tests(&mut can, &options).await; |
| 104 | run_can_tests(&mut can2, &options).await; | ||
| 91 | 105 | ||
| 92 | let mut i: u8 = 0; | 106 | info!("CAN Configured"); |
| 93 | loop { | ||
| 94 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | ||
| 95 | |||
| 96 | info!("Transmitting frame..."); | ||
| 97 | let tx_ts = Instant::now(); | ||
| 98 | can.write(&tx_frame).await; | ||
| 99 | |||
| 100 | let (frame, timestamp) = can.read().await.unwrap(); | ||
| 101 | info!("Frame received!"); | ||
| 102 | |||
| 103 | // Check data. | ||
| 104 | assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]); | ||
| 105 | |||
| 106 | info!("loopback time {}", timestamp); | ||
| 107 | info!("loopback frame {=u8}", frame.data()[0]); | ||
| 108 | let latency = timestamp.saturating_duration_since(tx_ts); | ||
| 109 | info!("loopback latency {} us", latency.as_micros()); | ||
| 110 | |||
| 111 | // Theoretical minimum latency is 55us, actual is usually ~80us | ||
| 112 | const MIN_LATENCY: Duration = Duration::from_micros(50); | ||
| 113 | // Was failing at 150 but we are not getting a real time stamp. I'm not | ||
| 114 | // sure if there are other delays | ||
| 115 | assert!( | ||
| 116 | MIN_LATENCY <= latency && latency <= options.max_latency, | ||
| 117 | "{} <= {} <= {}", | ||
| 118 | MIN_LATENCY, | ||
| 119 | latency, | ||
| 120 | options.max_latency | ||
| 121 | ); | ||
| 122 | |||
| 123 | i += 1; | ||
| 124 | if i > 10 { | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | let max_buffered = if options.second_fifo_working { 6 } else { 3 }; | ||
| 130 | |||
| 131 | // Below here, check that we can receive from both FIFO0 and FIFO0 | ||
| 132 | // Above we configured FIFO1 for extended ID packets. There are only 3 slots | ||
| 133 | // in each FIFO so make sure we write enough to fill them both up before reading. | ||
| 134 | for i in 0..3 { | ||
| 135 | // Try filling up the RX FIFO0 buffers with standard packets | ||
| 136 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | ||
| 137 | info!("Transmitting frame {}", i); | ||
| 138 | can.write(&tx_frame).await; | ||
| 139 | } | ||
| 140 | for i in 3..max_buffered { | ||
| 141 | // Try filling up the RX FIFO0 buffers with extended packets | ||
| 142 | let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap(); | ||
| 143 | info!("Transmitting frame {}", i); | ||
| 144 | can.write(&tx_frame).await; | ||
| 145 | } | ||
| 146 | |||
| 147 | // Try and receive all 6 packets | ||
| 148 | for i in 0..max_buffered { | ||
| 149 | let (frame, _ts) = can.read().await.unwrap(); | ||
| 150 | match frame.id() { | ||
| 151 | embedded_can::Id::Extended(id) => { | ||
| 152 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 153 | } | ||
| 154 | embedded_can::Id::Standard(id) => { | ||
| 155 | info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
| 159 | 107 | ||
| 160 | // Test again with a split | 108 | // Test again with a split |
| 161 | let (mut tx, mut rx) = can.split(); | 109 | let (mut tx, mut rx) = can.split(); |
| 162 | for i in 0..3 { | 110 | let (mut tx2, mut rx2) = can2.split(); |
| 163 | // Try filling up the RX FIFO0 buffers with standard packets | 111 | run_split_can_tests(&mut tx, &mut rx, &options).await; |
| 164 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | 112 | run_split_can_tests(&mut tx2, &mut rx2, &options).await; |
| 165 | info!("Transmitting frame {}", i); | ||
| 166 | tx.write(&tx_frame).await; | ||
| 167 | } | ||
| 168 | for i in 3..max_buffered { | ||
| 169 | // Try filling up the RX FIFO0 buffers with extended packets | ||
| 170 | let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap(); | ||
| 171 | info!("Transmitting frame {}", i); | ||
| 172 | tx.write(&tx_frame).await; | ||
| 173 | } | ||
| 174 | |||
| 175 | // Try and receive all 6 packets | ||
| 176 | for i in 0..max_buffered { | ||
| 177 | let (frame, _ts) = rx.read().await.unwrap(); | ||
| 178 | match frame.id() { | ||
| 179 | embedded_can::Id::Extended(id) => { | ||
| 180 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 181 | } | ||
| 182 | embedded_can::Id::Standard(id) => { | ||
| 183 | info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | 113 | ||
| 188 | info!("Test OK"); | 114 | info!("Test OK"); |
| 189 | cortex_m::asm::bkpt(); | 115 | cortex_m::asm::bkpt(); |
diff --git a/tests/stm32/src/bin/ucpd.rs b/tests/stm32/src/bin/ucpd.rs new file mode 100644 index 000000000..c09334ec8 --- /dev/null +++ b/tests/stm32/src/bin/ucpd.rs | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | // required-features: ucpd | ||
| 2 | #![no_std] | ||
| 3 | #![no_main] | ||
| 4 | #[path = "../common.rs"] | ||
| 5 | mod common; | ||
| 6 | |||
| 7 | use common::*; | ||
| 8 | use defmt::{assert, assert_eq}; | ||
| 9 | use embassy_executor::Spawner; | ||
| 10 | use embassy_futures::join::join; | ||
| 11 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, RxError, Ucpd}; | ||
| 12 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 13 | use embassy_time::Timer; | ||
| 14 | |||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | UCPD1_2 => ucpd::InterruptHandler<peripherals::UCPD1>, ucpd::InterruptHandler<peripherals::UCPD2>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | static SRC_TO_SNK: [u8; 6] = [0, 1, 2, 3, 4, 5]; | ||
| 20 | static SNK_TO_SRC: [u8; 4] = [9, 8, 7, 6]; | ||
| 21 | |||
| 22 | async fn wait_for_vstate<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>, vstate: CcVState) { | ||
| 23 | let (mut cc1, mut _cc2) = cc_phy.vstate(); | ||
| 24 | while cc1 != vstate { | ||
| 25 | (cc1, _cc2) = cc_phy.wait_for_vstate_change().await; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | async fn source( | ||
| 30 | mut ucpd: Ucpd<'static, peripherals::UCPD1>, | ||
| 31 | rx_dma: peripherals::DMA1_CH1, | ||
| 32 | tx_dma: peripherals::DMA1_CH2, | ||
| 33 | ) { | ||
| 34 | debug!("source: setting default current pull-up"); | ||
| 35 | ucpd.cc_phy().set_pull(CcPull::SourceDefaultUsb); | ||
| 36 | |||
| 37 | // Wait for default sink. | ||
| 38 | debug!("source: wait for sink"); | ||
| 39 | wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await; | ||
| 40 | |||
| 41 | // Advertise a higher current by changing the pull-up resistor. | ||
| 42 | debug!("source: sink detected, setting 3.0A current pull-up"); | ||
| 43 | ucpd.cc_phy().set_pull(CcPull::Source3_0A); | ||
| 44 | |||
| 45 | let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1); | ||
| 46 | |||
| 47 | // Listen for an incoming message | ||
| 48 | debug!("source: wait for message from sink"); | ||
| 49 | let mut snk_to_src_buf = [0_u8; 30]; | ||
| 50 | let n = unwrap!(pd_phy.receive(snk_to_src_buf.as_mut()).await); | ||
| 51 | assert_eq!(n, SNK_TO_SRC.len()); | ||
| 52 | assert_eq!(&snk_to_src_buf[..n], SNK_TO_SRC.as_slice()); | ||
| 53 | |||
| 54 | // Send message | ||
| 55 | debug!("source: message received, sending message"); | ||
| 56 | unwrap!(pd_phy.transmit(SRC_TO_SNK.as_slice()).await); | ||
| 57 | |||
| 58 | // Wait for hard-reset | ||
| 59 | debug!("source: message sent, waiting for hard-reset"); | ||
| 60 | assert!(matches!( | ||
| 61 | pd_phy.receive(snk_to_src_buf.as_mut()).await, | ||
| 62 | Err(RxError::HardReset) | ||
| 63 | )); | ||
| 64 | } | ||
| 65 | |||
| 66 | async fn sink( | ||
| 67 | mut ucpd: Ucpd<'static, peripherals::UCPD2>, | ||
| 68 | rx_dma: peripherals::DMA1_CH3, | ||
| 69 | tx_dma: peripherals::DMA1_CH4, | ||
| 70 | ) { | ||
| 71 | debug!("sink: setting pull down"); | ||
| 72 | ucpd.cc_phy().set_pull(CcPull::Sink); | ||
| 73 | |||
| 74 | // Wait for default source. | ||
| 75 | debug!("sink: waiting for default vstate"); | ||
| 76 | wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await; | ||
| 77 | |||
| 78 | // Wait higher current pull-up. | ||
| 79 | //debug!("sink: source default vstate detected, waiting for 3.0A vstate"); | ||
| 80 | //wait_for_vstate(ucpd.cc_phy(), CcVState::HIGHEST).await; | ||
| 81 | //debug!("sink: source 3.0A vstate detected"); | ||
| 82 | // TODO: not working yet, why? no idea, replace with timer for now | ||
| 83 | Timer::after_millis(100).await; | ||
| 84 | |||
| 85 | let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1); | ||
| 86 | |||
| 87 | // Send message | ||
| 88 | debug!("sink: sending message"); | ||
| 89 | unwrap!(pd_phy.transmit(SNK_TO_SRC.as_slice()).await); | ||
| 90 | |||
| 91 | // Listen for an incoming message | ||
| 92 | debug!("sink: message sent, waiting for message from source"); | ||
| 93 | let mut src_to_snk_buf = [0_u8; 30]; | ||
| 94 | let n = unwrap!(pd_phy.receive(src_to_snk_buf.as_mut()).await); | ||
| 95 | assert_eq!(n, SRC_TO_SNK.len()); | ||
| 96 | assert_eq!(&src_to_snk_buf[..n], SRC_TO_SNK.as_slice()); | ||
| 97 | |||
| 98 | // Send hard reset | ||
| 99 | debug!("sink: message received, sending hard-reset"); | ||
| 100 | unwrap!(pd_phy.transmit_hardreset().await); | ||
| 101 | } | ||
| 102 | |||
| 103 | #[embassy_executor::main] | ||
| 104 | async fn main(_spawner: Spawner) { | ||
| 105 | let p = embassy_stm32::init(config()); | ||
| 106 | info!("Hello World!"); | ||
| 107 | |||
| 108 | // Wire between PD0 and PA8 | ||
| 109 | let ucpd1 = Ucpd::new(p.UCPD1, Irqs {}, p.PA8, p.PB15); | ||
| 110 | let ucpd2 = Ucpd::new(p.UCPD2, Irqs {}, p.PD0, p.PD2); | ||
| 111 | |||
| 112 | join( | ||
| 113 | source(ucpd1, p.DMA1_CH1, p.DMA1_CH2), | ||
| 114 | sink(ucpd2, p.DMA1_CH3, p.DMA1_CH4), | ||
| 115 | ) | ||
| 116 | .await; | ||
| 117 | |||
| 118 | info!("Test OK"); | ||
| 119 | cortex_m::asm::bkpt(); | ||
| 120 | } | ||
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 3297ea7e2..0e555efc8 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs | |||
| @@ -140,6 +140,7 @@ define_peris!( | |||
| 140 | ); | 140 | ); |
| 141 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] | 141 | #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] |
| 142 | define_peris!( | 142 | define_peris!( |
| 143 | CRYP_IN_DMA = DMA1_CH0, CRYP_OUT_DMA = DMA1_CH1, | ||
| 143 | UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1, | 144 | UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH0, UART_RX_DMA = DMA1_CH1, |
| 144 | SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1, | 145 | SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PB5, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH0, SPI_RX_DMA = DMA1_CH1, |
| 145 | ADC = ADC1, DAC = DAC1, DAC_PIN = PA4, | 146 | ADC = ADC1, DAC = DAC1, DAC_PIN = PA4, |
| @@ -250,13 +251,6 @@ define_peris!( | |||
| 250 | ); | 251 | ); |
| 251 | 252 | ||
| 252 | pub fn config() -> Config { | 253 | pub fn config() -> Config { |
| 253 | // Setting this bit is mandatory to use PG[15:2]. | ||
| 254 | #[cfg(feature = "stm32u5a5zj")] | ||
| 255 | embassy_stm32::pac::PWR.svmcr().modify(|w| { | ||
| 256 | w.set_io2sv(true); | ||
| 257 | w.set_io2vmen(true); | ||
| 258 | }); | ||
| 259 | |||
| 260 | #[allow(unused_mut)] | 254 | #[allow(unused_mut)] |
| 261 | let mut config = Config::default(); | 255 | let mut config = Config::default(); |
| 262 | 256 | ||
