diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-03-15 18:51:09 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-03-15 18:51:09 +0000 |
| commit | c580d4c490239762b6e68ee9e25599bfe86ed926 (patch) | |
| tree | 39a1c339e3785072564ecc0b3820233c58138219 /tests/stm32/src | |
| parent | a92a73abe46967a9ca511aa21265b7c338e11c6f (diff) | |
| parent | 0f0301843487a921a5ef57eb8972971181ea0024 (diff) | |
Merge pull request #2701 from timokroeger/stm32-ucpd
STM32 UCPD CI Test
Diffstat (limited to 'tests/stm32/src')
| -rw-r--r-- | tests/stm32/src/bin/ucpd.rs | 120 |
1 files changed, 120 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..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 | } | ||
