diff options
| author | Timo Kröger <[email protected]> | 2024-03-15 17:45:48 +0100 |
|---|---|---|
| committer | Timo Kröger <[email protected]> | 2024-03-15 17:49:15 +0100 |
| commit | 067e677ae5c3c765bca1db6e4cb7aef5de163086 (patch) | |
| tree | 80ac059d7a21d7415c676641dea81e479918c275 /tests/stm32/src/bin/ucpd.rs | |
| parent | 21e2499f353c995d71710a2ed62d6f3914d6d60c (diff) | |
[UCPD] Add unit test for stm32g071rb board
One test for changing the CC line pull-up resistor is skipped for now.
Diffstat (limited to 'tests/stm32/src/bin/ucpd.rs')
| -rw-r--r-- | tests/stm32/src/bin/ucpd.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/tests/stm32/src/bin/ucpd.rs b/tests/stm32/src/bin/ucpd.rs new file mode 100644 index 000000000..daaa56c32 --- /dev/null +++ b/tests/stm32/src/bin/ucpd.rs | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #[path = "../common.rs"] | ||
| 4 | mod common; | ||
| 5 | |||
| 6 | use common::*; | ||
| 7 | use defmt::{assert, assert_eq}; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_futures::join::join; | ||
| 10 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, RxError, Ucpd}; | ||
| 11 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 12 | use embassy_time::Timer; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | UCPD1_2 => ucpd::InterruptHandler<peripherals::UCPD1>, ucpd::InterruptHandler<peripherals::UCPD2>; | ||
| 16 | }); | ||
| 17 | |||
| 18 | static SRC_TO_SNK: [u8; 6] = [0, 1, 2, 3, 4, 5]; | ||
| 19 | static SNK_TO_SRC: [u8; 4] = [9, 8, 7, 6]; | ||
| 20 | |||
| 21 | async fn wait_for_vstate<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>, vstate: CcVState) { | ||
| 22 | let (mut cc1, mut _cc2) = cc_phy.vstate(); | ||
| 23 | while cc1 != vstate { | ||
| 24 | (cc1, _cc2) = cc_phy.wait_for_vstate_change().await; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | async fn source( | ||
| 29 | mut ucpd: Ucpd<'static, peripherals::UCPD1>, | ||
| 30 | rx_dma: peripherals::DMA1_CH1, | ||
| 31 | tx_dma: peripherals::DMA1_CH2, | ||
| 32 | ) { | ||
| 33 | debug!("source: setting default current pull-up"); | ||
| 34 | ucpd.cc_phy().set_pull(CcPull::SourceDefaultUsb); | ||
| 35 | |||
| 36 | // Wait for default sink. | ||
| 37 | debug!("source: wait for sink"); | ||
| 38 | wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await; | ||
| 39 | |||
| 40 | // Advertise a higher current by changing the pull-up resistor. | ||
| 41 | debug!("source: sink detected, setting 3.0A current pull-up"); | ||
| 42 | ucpd.cc_phy().set_pull(CcPull::Source3_0A); | ||
| 43 | |||
| 44 | let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1); | ||
| 45 | |||
| 46 | // Listen for an incoming message | ||
| 47 | debug!("source: wait for message from sink"); | ||
| 48 | let mut snk_to_src_buf = [0_u8; 30]; | ||
| 49 | let n = unwrap!(pd_phy.receive(snk_to_src_buf.as_mut()).await); | ||
| 50 | assert_eq!(n, SNK_TO_SRC.len()); | ||
| 51 | assert_eq!(&snk_to_src_buf[..n], SNK_TO_SRC.as_slice()); | ||
| 52 | |||
| 53 | // Send message | ||
| 54 | debug!("source: message received, sending message"); | ||
| 55 | unwrap!(pd_phy.transmit(SRC_TO_SNK.as_slice()).await); | ||
| 56 | |||
| 57 | // Wait for hard-reset | ||
| 58 | debug!("source: message sent, waiting for hard-reset"); | ||
| 59 | assert!(matches!( | ||
| 60 | pd_phy.receive(snk_to_src_buf.as_mut()).await, | ||
| 61 | Err(RxError::HardReset) | ||
| 62 | )); | ||
| 63 | } | ||
| 64 | |||
| 65 | async fn sink( | ||
| 66 | mut ucpd: Ucpd<'static, peripherals::UCPD2>, | ||
| 67 | rx_dma: peripherals::DMA1_CH3, | ||
| 68 | tx_dma: peripherals::DMA1_CH4, | ||
| 69 | ) { | ||
| 70 | debug!("sink: setting pull down"); | ||
| 71 | ucpd.cc_phy().set_pull(CcPull::Sink); | ||
| 72 | |||
| 73 | // Wait for default source. | ||
| 74 | debug!("sink: waiting for default vstate"); | ||
| 75 | wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await; | ||
| 76 | |||
| 77 | // Wait higher current pull-up. | ||
| 78 | //debug!("sink: source default vstate detected, waiting for 3.0A vstate"); | ||
| 79 | //wait_for_vstate(ucpd.cc_phy(), CcVState::HIGHEST).await; | ||
| 80 | //debug!("sink: source 3.0A vstate detected"); | ||
| 81 | // TODO: not working yet, why? no idea, replace with timer for now | ||
| 82 | Timer::after_millis(100).await; | ||
| 83 | |||
| 84 | let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1); | ||
| 85 | |||
| 86 | // Send message | ||
| 87 | debug!("sink: sending message"); | ||
| 88 | unwrap!(pd_phy.transmit(SNK_TO_SRC.as_slice()).await); | ||
| 89 | |||
| 90 | // Listen for an incoming message | ||
| 91 | debug!("sink: message sent, waiting for message from source"); | ||
| 92 | let mut src_to_snk_buf = [0_u8; 30]; | ||
| 93 | let n = unwrap!(pd_phy.receive(src_to_snk_buf.as_mut()).await); | ||
| 94 | assert_eq!(n, SRC_TO_SNK.len()); | ||
| 95 | assert_eq!(&src_to_snk_buf[..n], SRC_TO_SNK.as_slice()); | ||
| 96 | |||
| 97 | // Send hard reset | ||
| 98 | debug!("sink: message received, sending hard-reset"); | ||
| 99 | unwrap!(pd_phy.transmit_hardreset().await); | ||
| 100 | } | ||
| 101 | |||
| 102 | #[embassy_executor::main] | ||
| 103 | async fn main(_spawner: Spawner) { | ||
| 104 | let p = embassy_stm32::init(config()); | ||
| 105 | info!("Hello World!"); | ||
| 106 | |||
| 107 | // Wire between PD0 and PA8 | ||
| 108 | let ucpd1 = Ucpd::new(p.UCPD1, Irqs {}, p.PA8, p.PB15); | ||
| 109 | let ucpd2 = Ucpd::new(p.UCPD2, Irqs {}, p.PD0, p.PD2); | ||
| 110 | |||
| 111 | join( | ||
| 112 | source(ucpd1, p.DMA1_CH1, p.DMA1_CH2), | ||
| 113 | sink(ucpd2, p.DMA1_CH3, p.DMA1_CH4), | ||
| 114 | ) | ||
| 115 | .await; | ||
| 116 | |||
| 117 | info!("Test OK"); | ||
| 118 | cortex_m::asm::bkpt(); | ||
| 119 | } | ||
