diff options
| author | Timo Kröger <[email protected]> | 2024-03-08 20:36:37 +0100 |
|---|---|---|
| committer | Timo Kröger <[email protected]> | 2024-03-12 08:14:42 +0100 |
| commit | 89504f51629d0ab81070db91c3eb5b96b1e41fcb (patch) | |
| tree | 0656fb3800905b20f85320306569b965f72ad6cc | |
| parent | 99854ff840fdd12d7562923f6a9ef2d39e1c9f17 (diff) | |
[UCPD] Split into CC and PD phy
PD3.0 spec requires concurrent control of CC resistors for collision avoidance.
Needed to introduce some "ref counting" (its just a bool) for drop code.
| -rw-r--r-- | embassy-stm32/src/ucpd.rs | 211 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/usb_c_pd.rs | 17 |
2 files changed, 144 insertions, 84 deletions
diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index d1b793e26..2120716ef 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs | |||
| @@ -16,11 +16,11 @@ | |||
| 16 | 16 | ||
| 17 | use core::future::poll_fn; | 17 | use core::future::poll_fn; |
| 18 | use core::marker::PhantomData; | 18 | use core::marker::PhantomData; |
| 19 | use core::sync::atomic::Ordering; | ||
| 19 | use core::task::Poll; | 20 | use core::task::Poll; |
| 20 | 21 | ||
| 21 | use embassy_hal_internal::drop::OnDrop; | 22 | use embassy_hal_internal::drop::OnDrop; |
| 22 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | 23 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; |
| 23 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 24 | 24 | ||
| 25 | use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; | 25 | use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; |
| 26 | use crate::interrupt; | 26 | use crate::interrupt; |
| @@ -53,22 +53,15 @@ pub enum CcPull { | |||
| 53 | 53 | ||
| 54 | /// UCPD driver. | 54 | /// UCPD driver. |
| 55 | pub struct Ucpd<'d, T: Instance> { | 55 | pub struct Ucpd<'d, T: Instance> { |
| 56 | _peri: PeripheralRef<'d, T>, | 56 | cc_phy: CcPhy<'d, T>, |
| 57 | } | ||
| 58 | |||
| 59 | impl<'d, T: Instance> Drop for Ucpd<'d, T> { | ||
| 60 | fn drop(&mut self) { | ||
| 61 | T::REGS.cfgr1().write(|w| w.set_ucpden(false)); | ||
| 62 | } | ||
| 63 | } | 57 | } |
| 64 | 58 | ||
| 65 | impl<'d, T: Instance> Ucpd<'d, T> { | 59 | impl<'d, T: Instance> Ucpd<'d, T> { |
| 66 | /// Creates a new UCPD driver instance. | 60 | /// Creates a new UCPD driver instance. |
| 67 | pub fn new( | 61 | pub fn new( |
| 68 | peri: impl Peripheral<P = T> + 'd, | 62 | _peri: impl Peripheral<P = T> + 'd, |
| 69 | _cc1: impl Peripheral<P = impl Cc1Pin<T>> + 'd, | 63 | _cc1: impl Peripheral<P = impl Cc1Pin<T>> + 'd, |
| 70 | _cc2: impl Peripheral<P = impl Cc2Pin<T>> + 'd, | 64 | _cc2: impl Peripheral<P = impl Cc2Pin<T>> + 'd, |
| 71 | cc_pull: CcPull, | ||
| 72 | ) -> Self { | 65 | ) -> Self { |
| 73 | T::enable_and_reset(); | 66 | T::enable_and_reset(); |
| 74 | 67 | ||
| @@ -99,7 +92,94 @@ impl<'d, T: Instance> Ucpd<'d, T> { | |||
| 99 | w.set_ucpden(true); | 92 | w.set_ucpden(true); |
| 100 | }); | 93 | }); |
| 101 | 94 | ||
| 102 | r.cr().write(|w| { | 95 | Self { |
| 96 | cc_phy: CcPhy { _lifetime: PhantomData }, | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | /// Returns the TypeC CC PHY. | ||
| 101 | pub fn cc_phy(&mut self) -> &mut CcPhy<'d, T> { | ||
| 102 | &mut self.cc_phy | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Splits the UCPD driver into a TypeC PHY to control and monitor CC voltage | ||
| 106 | /// and a Power Delivery (PD) PHY with receiver and transmitter. | ||
| 107 | pub fn split_pd_phy( | ||
| 108 | self, | ||
| 109 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, | ||
| 110 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, | ||
| 111 | cc_sel: CcSel, | ||
| 112 | ) -> (CcPhy<'d, T>, PdPhy<'d, T>) { | ||
| 113 | let r = T::REGS; | ||
| 114 | |||
| 115 | // TODO: Currently only SOP messages are supported. | ||
| 116 | r.tx_ordsetr().write(|w| w.set_txordset(0b10001_11000_11000_11000)); | ||
| 117 | |||
| 118 | r.cfgr1().modify(|w| { | ||
| 119 | // TODO: Currently only hard reset and SOP messages can be received. | ||
| 120 | w.set_rxordseten(0b1001); | ||
| 121 | |||
| 122 | // Enable DMA | ||
| 123 | w.set_txdmaen(true); | ||
| 124 | w.set_rxdmaen(true); | ||
| 125 | }); | ||
| 126 | |||
| 127 | // Enable the receiver on one of the two CC lines. | ||
| 128 | r.cr().modify(|w| { | ||
| 129 | w.set_phyccsel(cc_sel); | ||
| 130 | w.set_phyrxen(true); | ||
| 131 | }); | ||
| 132 | |||
| 133 | // Enable hard reset receive interrupt. | ||
| 134 | r.imr().modify(|w| w.set_rxhrstdetie(true)); | ||
| 135 | |||
| 136 | // Both parts must be dropped before the peripheral can be disabled. | ||
| 137 | T::state().drop_not_ready.store(true, Ordering::Relaxed); | ||
| 138 | |||
| 139 | into_ref!(rx_dma, tx_dma); | ||
| 140 | let rx_dma_req = rx_dma.request(); | ||
| 141 | let tx_dma_req = tx_dma.request(); | ||
| 142 | ( | ||
| 143 | self.cc_phy, | ||
| 144 | PdPhy { | ||
| 145 | _lifetime: PhantomData, | ||
| 146 | rx_dma_ch: rx_dma.map_into(), | ||
| 147 | rx_dma_req, | ||
| 148 | tx_dma_ch: tx_dma.map_into(), | ||
| 149 | tx_dma_req, | ||
| 150 | }, | ||
| 151 | ) | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | /// Control and monitoring of TypeC CC pin functionailty. | ||
| 156 | pub struct CcPhy<'d, T: Instance> { | ||
| 157 | _lifetime: PhantomData<&'d mut T>, | ||
| 158 | } | ||
| 159 | |||
| 160 | impl<'d, T: Instance> Drop for CcPhy<'d, T> { | ||
| 161 | fn drop(&mut self) { | ||
| 162 | let r = T::REGS; | ||
| 163 | r.cr().modify(|w| { | ||
| 164 | w.set_cc1tcdis(true); | ||
| 165 | w.set_cc2tcdis(true); | ||
| 166 | w.set_ccenable(Ccenable::DISABLED); | ||
| 167 | }); | ||
| 168 | |||
| 169 | // Check if the PdPhy part was dropped already. | ||
| 170 | let drop_not_ready = &T::state().drop_not_ready; | ||
| 171 | if drop_not_ready.load(Ordering::Relaxed) { | ||
| 172 | drop_not_ready.store(true, Ordering::Relaxed); | ||
| 173 | } else { | ||
| 174 | r.cfgr1().write(|w| w.set_ucpden(false)); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | impl<'d, T: Instance> CcPhy<'d, T> { | ||
| 180 | /// Sets the pull-up/pull-down resistor values exposed on the CC pins. | ||
| 181 | pub fn set_pull(&mut self, cc_pull: CcPull) { | ||
| 182 | T::REGS.cr().write(|w| { | ||
| 103 | w.set_anamode(if cc_pull == CcPull::Sink { | 183 | w.set_anamode(if cc_pull == CcPull::Sink { |
| 104 | Anamode::SINK | 184 | Anamode::SINK |
| 105 | } else { | 185 | } else { |
| @@ -116,10 +196,6 @@ impl<'d, T: Instance> Ucpd<'d, T> { | |||
| 116 | } else { | 196 | } else { |
| 117 | Ccenable::DISABLED | 197 | Ccenable::DISABLED |
| 118 | }); | 198 | }); |
| 119 | |||
| 120 | // Make sure detector is enabled on both pins. | ||
| 121 | w.set_cc1tcdis(false); | ||
| 122 | w.set_cc2tcdis(false); | ||
| 123 | }); | 199 | }); |
| 124 | 200 | ||
| 125 | // Disable dead-battery pull-down resistors which are enabled by default on boot. | 201 | // Disable dead-battery pull-down resistors which are enabled by default on boot. |
| @@ -130,30 +206,27 @@ impl<'d, T: Instance> Ucpd<'d, T> { | |||
| 130 | .cr3() | 206 | .cr3() |
| 131 | .modify(|w| w.set_ucpd1_dbdis(cc_pull != CcPull::SinkDeadBattery)); | 207 | .modify(|w| w.set_ucpd1_dbdis(cc_pull != CcPull::SinkDeadBattery)); |
| 132 | }); | 208 | }); |
| 133 | |||
| 134 | into_ref!(peri); | ||
| 135 | Self { _peri: peri } | ||
| 136 | } | 209 | } |
| 137 | 210 | ||
| 138 | /// Returns the current voltage level of CC1 and CC2 pin as tuple. | 211 | /// Returns the current voltage level of CC1 and CC2 pin as tuple. |
| 139 | /// | 212 | /// |
| 140 | /// Interpretation of the voltage levels depends on the configured CC line | 213 | /// Interpretation of the voltage levels depends on the configured CC line |
| 141 | /// pull-up/pull-down resistance. | 214 | /// pull-up/pull-down resistance. |
| 142 | pub fn cc_vstate(&self) -> (CcVState, CcVState) { | 215 | pub fn vstate(&self) -> (CcVState, CcVState) { |
| 143 | let sr = T::REGS.sr().read(); | 216 | let sr = T::REGS.sr().read(); |
| 144 | (sr.typec_vstate_cc1(), sr.typec_vstate_cc2()) | 217 | (sr.typec_vstate_cc1(), sr.typec_vstate_cc2()) |
| 145 | } | 218 | } |
| 146 | 219 | ||
| 147 | /// Waits for a change in voltage state on either CC line. | 220 | /// Waits for a change in voltage state on either CC line. |
| 148 | pub async fn wait_for_cc_vstate_change(&self) -> (CcVState, CcVState) { | 221 | pub async fn wait_for_vstate_change(&self) -> (CcVState, CcVState) { |
| 149 | let _on_drop = OnDrop::new(|| self.enable_cc_interrupts(false)); | 222 | let _on_drop = OnDrop::new(|| self.enable_cc_interrupts(false)); |
| 150 | let prev_vstate = self.cc_vstate(); | 223 | let prev_vstate = self.vstate(); |
| 151 | poll_fn(|cx| { | 224 | poll_fn(|cx| { |
| 152 | let vstate = self.cc_vstate(); | 225 | let vstate = self.vstate(); |
| 153 | if vstate != prev_vstate { | 226 | if vstate != prev_vstate { |
| 154 | Poll::Ready(vstate) | 227 | Poll::Ready(vstate) |
| 155 | } else { | 228 | } else { |
| 156 | T::waker().register(cx.waker()); | 229 | T::state().waker.register(cx.waker()); |
| 157 | self.enable_cc_interrupts(true); | 230 | self.enable_cc_interrupts(true); |
| 158 | Poll::Pending | 231 | Poll::Pending |
| 159 | } | 232 | } |
| @@ -167,48 +240,6 @@ impl<'d, T: Instance> Ucpd<'d, T> { | |||
| 167 | w.set_typecevt2ie(enable); | 240 | w.set_typecevt2ie(enable); |
| 168 | }); | 241 | }); |
| 169 | } | 242 | } |
| 170 | |||
| 171 | /// Returns PD receiver and transmitter. | ||
| 172 | pub fn pd_phy( | ||
| 173 | &mut self, | ||
| 174 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, | ||
| 175 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, | ||
| 176 | cc_sel: CcSel, | ||
| 177 | ) -> PdPhy<'_, T> { | ||
| 178 | let r = T::REGS; | ||
| 179 | |||
| 180 | // TODO: Currently only SOP messages are supported. | ||
| 181 | r.tx_ordsetr().write(|w| w.set_txordset(0b10001_11000_11000_11000)); | ||
| 182 | |||
| 183 | r.cfgr1().modify(|w| { | ||
| 184 | // TODO: Currently only hard reset and SOP messages can be received. | ||
| 185 | w.set_rxordseten(0b1001); | ||
| 186 | |||
| 187 | // Enable DMA | ||
| 188 | w.set_txdmaen(true); | ||
| 189 | w.set_rxdmaen(true); | ||
| 190 | }); | ||
| 191 | |||
| 192 | // Enable the receiver on one of the two CC lines. | ||
| 193 | r.cr().modify(|w| { | ||
| 194 | w.set_phyccsel(cc_sel); | ||
| 195 | w.set_phyrxen(true); | ||
| 196 | }); | ||
| 197 | |||
| 198 | // Enable hard reset receive interrupt. | ||
| 199 | r.imr().modify(|w| w.set_rxhrstdetie(true)); | ||
| 200 | |||
| 201 | into_ref!(rx_dma, tx_dma); | ||
| 202 | let rx_dma_req = rx_dma.request(); | ||
| 203 | let tx_dma_req = tx_dma.request(); | ||
| 204 | PdPhy { | ||
| 205 | _ucpd: self, | ||
| 206 | rx_dma_ch: rx_dma.map_into(), | ||
| 207 | rx_dma_req, | ||
| 208 | tx_dma_ch: tx_dma.map_into(), | ||
| 209 | tx_dma_req, | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | 243 | } |
| 213 | 244 | ||
| 214 | /// Receive Error. | 245 | /// Receive Error. |
| @@ -238,7 +269,7 @@ pub enum TxError { | |||
| 238 | 269 | ||
| 239 | /// Power Delivery (PD) PHY. | 270 | /// Power Delivery (PD) PHY. |
| 240 | pub struct PdPhy<'d, T: Instance> { | 271 | pub struct PdPhy<'d, T: Instance> { |
| 241 | _ucpd: &'d Ucpd<'d, T>, | 272 | _lifetime: PhantomData<&'d mut T>, |
| 242 | rx_dma_ch: PeripheralRef<'d, AnyChannel>, | 273 | rx_dma_ch: PeripheralRef<'d, AnyChannel>, |
| 243 | rx_dma_req: Request, | 274 | rx_dma_req: Request, |
| 244 | tx_dma_ch: PeripheralRef<'d, AnyChannel>, | 275 | tx_dma_ch: PeripheralRef<'d, AnyChannel>, |
| @@ -247,7 +278,16 @@ pub struct PdPhy<'d, T: Instance> { | |||
| 247 | 278 | ||
| 248 | impl<'d, T: Instance> Drop for PdPhy<'d, T> { | 279 | impl<'d, T: Instance> Drop for PdPhy<'d, T> { |
| 249 | fn drop(&mut self) { | 280 | fn drop(&mut self) { |
| 250 | T::REGS.cr().modify(|w| w.set_phyrxen(false)); | 281 | let r = T::REGS; |
| 282 | r.cr().modify(|w| w.set_phyrxen(false)); | ||
| 283 | |||
| 284 | // Check if the Type-C part was dropped already. | ||
| 285 | let drop_not_ready = &T::state().drop_not_ready; | ||
| 286 | if drop_not_ready.load(Ordering::Relaxed) { | ||
| 287 | drop_not_ready.store(true, Ordering::Relaxed); | ||
| 288 | } else { | ||
| 289 | r.cfgr1().write(|w| w.set_ucpden(false)); | ||
| 290 | } | ||
| 251 | } | 291 | } |
| 252 | } | 292 | } |
| 253 | 293 | ||
| @@ -316,7 +356,7 @@ impl<'d, T: Instance> PdPhy<'d, T> { | |||
| 316 | }); | 356 | }); |
| 317 | Poll::Ready(ret) | 357 | Poll::Ready(ret) |
| 318 | } else { | 358 | } else { |
| 319 | T::waker().register(cx.waker()); | 359 | T::state().waker.register(cx.waker()); |
| 320 | self.enable_rx_interrupt(true); | 360 | self.enable_rx_interrupt(true); |
| 321 | Poll::Pending | 361 | Poll::Pending |
| 322 | } | 362 | } |
| @@ -383,7 +423,7 @@ impl<'d, T: Instance> PdPhy<'d, T> { | |||
| 383 | } else if sr.txmsgsent() { | 423 | } else if sr.txmsgsent() { |
| 384 | Poll::Ready(Ok(())) | 424 | Poll::Ready(Ok(())) |
| 385 | } else { | 425 | } else { |
| 386 | T::waker().register(cx.waker()); | 426 | T::state().waker.register(cx.waker()); |
| 387 | self.enable_tx_interrupts(true); | 427 | self.enable_tx_interrupts(true); |
| 388 | Poll::Pending | 428 | Poll::Pending |
| 389 | } | 429 | } |
| @@ -427,7 +467,7 @@ impl<'d, T: Instance> PdPhy<'d, T> { | |||
| 427 | } else if sr.hrstsent() { | 467 | } else if sr.hrstsent() { |
| 428 | Poll::Ready(Ok(())) | 468 | Poll::Ready(Ok(())) |
| 429 | } else { | 469 | } else { |
| 430 | T::waker().register(cx.waker()); | 470 | T::state().waker.register(cx.waker()); |
| 431 | self.enable_hardreset_interrupts(true); | 471 | self.enable_hardreset_interrupts(true); |
| 432 | Poll::Pending | 472 | Poll::Pending |
| 433 | } | 473 | } |
| @@ -483,18 +523,37 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 483 | } | 523 | } |
| 484 | 524 | ||
| 485 | // Wake the task to clear and re-enabled interrupts. | 525 | // Wake the task to clear and re-enabled interrupts. |
| 486 | T::waker().wake(); | 526 | T::state().waker.wake(); |
| 487 | } | 527 | } |
| 488 | } | 528 | } |
| 489 | 529 | ||
| 490 | /// UCPD instance trait. | 530 | /// UCPD instance trait. |
| 491 | pub trait Instance: sealed::Instance + RccPeripheral {} | 531 | pub trait Instance: sealed::Instance + RccPeripheral {} |
| 492 | 532 | ||
| 493 | pub(crate) mod sealed { | 533 | mod sealed { |
| 534 | use core::sync::atomic::AtomicBool; | ||
| 535 | |||
| 536 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 537 | |||
| 538 | pub struct State { | ||
| 539 | pub waker: AtomicWaker, | ||
| 540 | // Inverted logic for a default state of 0 so that the data goes into the .bss section. | ||
| 541 | pub drop_not_ready: AtomicBool, | ||
| 542 | } | ||
| 543 | |||
| 544 | impl State { | ||
| 545 | pub const fn new() -> Self { | ||
| 546 | Self { | ||
| 547 | waker: AtomicWaker::new(), | ||
| 548 | drop_not_ready: AtomicBool::new(false), | ||
| 549 | } | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 494 | pub trait Instance { | 553 | pub trait Instance { |
| 495 | type Interrupt: crate::interrupt::typelevel::Interrupt; | 554 | type Interrupt: crate::interrupt::typelevel::Interrupt; |
| 496 | const REGS: crate::pac::ucpd::Ucpd; | 555 | const REGS: crate::pac::ucpd::Ucpd; |
| 497 | fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker; | 556 | fn state() -> &'static crate::ucpd::sealed::State; |
| 498 | } | 557 | } |
| 499 | } | 558 | } |
| 500 | 559 | ||
| @@ -505,9 +564,9 @@ foreach_interrupt!( | |||
| 505 | 564 | ||
| 506 | const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; | 565 | const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; |
| 507 | 566 | ||
| 508 | fn waker() -> &'static AtomicWaker { | 567 | fn state() -> &'static crate::ucpd::sealed::State { |
| 509 | static WAKER: AtomicWaker = AtomicWaker::new(); | 568 | static STATE: crate::ucpd::sealed::State = crate::ucpd::sealed::State::new(); |
| 510 | &WAKER | 569 | &STATE |
| 511 | } | 570 | } |
| 512 | } | 571 | } |
| 513 | 572 | ||
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs index 14abd542f..0e80840df 100644 --- a/examples/stm32g4/src/bin/usb_c_pd.rs +++ b/examples/stm32g4/src/bin/usb_c_pd.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::{error, info, Format}; | 4 | use defmt::{error, info, Format}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::ucpd::{self, CcPull, CcSel, CcVState, Ucpd}; | 6 | use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; |
| 7 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 8 | use embassy_time::{with_timeout, Duration}; | 8 | use embassy_time::{with_timeout, Duration}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -16,17 +16,17 @@ enum CableOrientation { | |||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | // Returns true when the cable | 18 | // Returns true when the cable |
| 19 | async fn wait_attached<T: ucpd::Instance>(ucpd: &mut Ucpd<'_, T>) -> CableOrientation { | 19 | async fn wait_attached<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>) -> CableOrientation { |
| 20 | loop { | 20 | loop { |
| 21 | let (cc1, cc2) = ucpd.cc_vstate(); | 21 | let (cc1, cc2) = cc_phy.vstate(); |
| 22 | if cc1 == CcVState::LOWEST && cc2 == CcVState::LOWEST { | 22 | if cc1 == CcVState::LOWEST && cc2 == CcVState::LOWEST { |
| 23 | // Detached, wait until attached by monitoring the CC lines. | 23 | // Detached, wait until attached by monitoring the CC lines. |
| 24 | ucpd.wait_for_cc_vstate_change().await; | 24 | cc_phy.wait_for_vstate_change().await; |
| 25 | continue; | 25 | continue; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | // Attached, wait for CC lines to be stable for tCCDebounce (100..200ms). | 28 | // Attached, wait for CC lines to be stable for tCCDebounce (100..200ms). |
| 29 | if with_timeout(Duration::from_millis(100), ucpd.wait_for_cc_vstate_change()) | 29 | if with_timeout(Duration::from_millis(100), cc_phy.wait_for_vstate_change()) |
| 30 | .await | 30 | .await |
| 31 | .is_ok() | 31 | .is_ok() |
| 32 | { | 32 | { |
| @@ -50,10 +50,11 @@ async fn main(_spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | info!("Hello World!"); | 51 | info!("Hello World!"); |
| 52 | 52 | ||
| 53 | let mut ucpd = Ucpd::new(p.UCPD1, p.PB6, p.PB4, CcPull::Sink); | 53 | let mut ucpd = Ucpd::new(p.UCPD1, p.PB6, p.PB4); |
| 54 | ucpd.cc_phy().set_pull(CcPull::Sink); | ||
| 54 | 55 | ||
| 55 | info!("Waiting for USB connection..."); | 56 | info!("Waiting for USB connection..."); |
| 56 | let cable_orientation = wait_attached(&mut ucpd).await; | 57 | let cable_orientation = wait_attached(ucpd.cc_phy()).await; |
| 57 | info!("USB cable connected, orientation: {}", cable_orientation); | 58 | info!("USB cable connected, orientation: {}", cable_orientation); |
| 58 | 59 | ||
| 59 | let cc_sel = match cable_orientation { | 60 | let cc_sel = match cable_orientation { |
| @@ -67,7 +68,7 @@ async fn main(_spawner: Spawner) { | |||
| 67 | } | 68 | } |
| 68 | CableOrientation::DebugAccessoryMode => panic!("No PD communication in DAM"), | 69 | CableOrientation::DebugAccessoryMode => panic!("No PD communication in DAM"), |
| 69 | }; | 70 | }; |
| 70 | let mut pd_phy = ucpd.pd_phy(p.DMA1_CH1, p.DMA1_CH2, cc_sel); | 71 | let (_cc_phy, mut pd_phy) = ucpd.split_pd_phy(p.DMA1_CH1, p.DMA1_CH2, cc_sel); |
| 71 | 72 | ||
| 72 | loop { | 73 | loop { |
| 73 | // Enough space for the longest non-extended data message. | 74 | // Enough space for the longest non-extended data message. |
