aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-03-14 21:21:33 +0000
committerGitHub <[email protected]>2024-03-14 21:21:33 +0000
commit963fda240484e0105408185f955703e2c02f9187 (patch)
tree93cd3d8bfbbeb5a584eb57e010ca9e70f7ce20b8 /examples
parent23e8fd8337df379fd22df5839a5b7cde3892eb47 (diff)
parent7b80de5e3db69a3d348bc74f6294e8642a11785e (diff)
Merge pull request #2652 from timokroeger/stm32-ucpd
STM32 USB Type-C/USB Power Delivery Interface (UCPD)
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32g4/src/bin/usb_c_pd.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs
new file mode 100644
index 000000000..7caea634f
--- /dev/null
+++ b/examples/stm32g4/src/bin/usb_c_pd.rs
@@ -0,0 +1,86 @@
1#![no_std]
2#![no_main]
3
4use defmt::{error, info, Format};
5use embassy_executor::Spawner;
6use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd};
7use embassy_stm32::{bind_interrupts, peripherals, Config};
8use embassy_time::{with_timeout, Duration};
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 UCPD1 => ucpd::InterruptHandler<peripherals::UCPD1>;
13});
14
15#[derive(Debug, Format)]
16enum CableOrientation {
17 Normal,
18 Flipped,
19 DebugAccessoryMode,
20}
21
22// Returns true when the cable
23async fn wait_attached<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>) -> CableOrientation {
24 loop {
25 let (cc1, cc2) = cc_phy.vstate();
26 if cc1 == CcVState::LOWEST && cc2 == CcVState::LOWEST {
27 // Detached, wait until attached by monitoring the CC lines.
28 cc_phy.wait_for_vstate_change().await;
29 continue;
30 }
31
32 // Attached, wait for CC lines to be stable for tCCDebounce (100..200ms).
33 if with_timeout(Duration::from_millis(100), cc_phy.wait_for_vstate_change())
34 .await
35 .is_ok()
36 {
37 // State has changed, restart detection procedure.
38 continue;
39 };
40
41 // State was stable for the complete debounce period, check orientation.
42 return match (cc1, cc2) {
43 (_, CcVState::LOWEST) => CableOrientation::Normal, // CC1 connected
44 (CcVState::LOWEST, _) => CableOrientation::Flipped, // CC2 connected
45 _ => CableOrientation::DebugAccessoryMode, // Both connected (special cable)
46 };
47 }
48}
49
50#[embassy_executor::main]
51async fn main(_spawner: Spawner) {
52 let mut config = Config::default();
53 config.enable_ucpd1_dead_battery = true;
54 let p = embassy_stm32::init(config);
55
56 info!("Hello World!");
57
58 let mut ucpd = Ucpd::new(p.UCPD1, Irqs {}, p.PB6, p.PB4);
59 ucpd.cc_phy().set_pull(CcPull::Sink);
60
61 info!("Waiting for USB connection...");
62 let cable_orientation = wait_attached(ucpd.cc_phy()).await;
63 info!("USB cable connected, orientation: {}", cable_orientation);
64
65 let cc_sel = match cable_orientation {
66 CableOrientation::Normal => {
67 info!("Starting PD communication on CC1 pin");
68 CcSel::CC1
69 }
70 CableOrientation::Flipped => {
71 info!("Starting PD communication on CC2 pin");
72 CcSel::CC2
73 }
74 CableOrientation::DebugAccessoryMode => panic!("No PD communication in DAM"),
75 };
76 let (_cc_phy, mut pd_phy) = ucpd.split_pd_phy(p.DMA1_CH1, p.DMA1_CH2, cc_sel);
77
78 loop {
79 // Enough space for the longest non-extended data message.
80 let mut buf = [0_u8; 30];
81 match pd_phy.receive(buf.as_mut()).await {
82 Ok(n) => info!("USB PD RX: {=[u8]:?}", &buf[..n]),
83 Err(e) => error!("USB PD RX: {}", e),
84 }
85 }
86}