Skip to content

Commit f7c29a6

Browse files
committed
power-policy/type-c: Refactor to use deferred channel
Refactor to use deferred channel IPC and increase default timeout, add timeout to power policy command execution.
1 parent 383a4c0 commit f7c29a6

File tree

10 files changed

+253
-195
lines changed

10 files changed

+253
-195
lines changed

embedded-service/src/power/policy/action/policy.rs

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
//! Policy state machine
2+
use embassy_time::{with_timeout, Duration};
3+
24
use super::*;
35
use crate::power::policy::{device, Error, PowerCapability};
46
use crate::{error, info};
57

8+
/// Default timeout for device commands to prevent the policy from getting stuck
9+
const DEFAULT_TIMEOUT: Duration = Duration::from_millis(5000);
10+
611
/// Policy state machine control
712
pub struct Policy<'a, S: Kind> {
813
device: &'a device::Device,
@@ -42,23 +47,32 @@ impl<'a, S: Kind> Policy<'a, S> {
4247
}
4348
}
4449

45-
async fn disconnect_internal(&self) -> Result<(), Error> {
50+
/// Common disconnect function used by multiple states
51+
async fn disconnect_internal_no_timeout(&self) -> Result<(), Error> {
4652
info!("Device {} got disconnect request", self.device.id().0);
4753
self.device
48-
.execute_device_request(device::RequestData::Disconnect)
54+
.execute_device_command(device::CommandData::Disconnect)
4955
.await?
5056
.complete_or_err()?;
5157
self.device.set_state(device::State::Idle).await;
5258
self.device.exit_recovery().await;
5359
Ok(())
5460
}
5561

56-
/// Connect this device as a provider
57-
async fn connect_provider_internal(&self, capability: PowerCapability) -> Result<(), Error> {
62+
/// Common disconnect function used by multiple states
63+
async fn disconnect_internal(&self) -> Result<(), Error> {
64+
match with_timeout(DEFAULT_TIMEOUT, self.disconnect_internal_no_timeout()).await {
65+
Ok(r) => r,
66+
Err(_) => Err(Error::Timeout),
67+
}
68+
}
69+
70+
/// Common connect provider function used by multiple states
71+
async fn connect_provider_internal_no_timeout(&self, capability: PowerCapability) -> Result<(), Error> {
5872
info!("Device {} connecting provider", self.device.id().0);
5973

6074
self.device
61-
.execute_device_request(device::RequestData::ConnectProvider(capability))
75+
.execute_device_command(device::CommandData::ConnectProvider(capability))
6276
.await?
6377
.complete_or_err()?;
6478

@@ -68,18 +82,29 @@ impl<'a, S: Kind> Policy<'a, S> {
6882

6983
Ok(())
7084
}
85+
86+
/// Common connect provider function used by multiple states
87+
async fn connect_provider_internal(&self, capability: PowerCapability) -> Result<(), Error> {
88+
match with_timeout(DEFAULT_TIMEOUT, self.connect_provider_internal_no_timeout(capability)).await {
89+
Ok(r) => r,
90+
Err(_) => Err(Error::Timeout),
91+
}
92+
}
7193
}
7294

7395
// The policy can do nothing when no device is attached
7496
impl Policy<'_, Detached> {}
7597

7698
impl<'a> Policy<'a, Idle> {
7799
/// Connect this device as a consumer
78-
pub async fn connect_consumer(self, capability: PowerCapability) -> Result<Policy<'a, ConnectedConsumer>, Error> {
100+
pub async fn connect_consumer_no_timeout(
101+
self,
102+
capability: PowerCapability,
103+
) -> Result<Policy<'a, ConnectedConsumer>, Error> {
79104
info!("Device {} connecting consumer", self.device.id().0);
80105

81106
self.device
82-
.execute_device_request(device::RequestData::ConnectConsumer(capability))
107+
.execute_device_command(device::CommandData::ConnectConsumer(capability))
83108
.await?
84109
.complete_or_err()?;
85110

@@ -89,6 +114,23 @@ impl<'a> Policy<'a, Idle> {
89114
Ok(Policy::new(self.device))
90115
}
91116

117+
/// Connect this device as a consumer
118+
pub async fn connect_consumer(self, capability: PowerCapability) -> Result<Policy<'a, ConnectedConsumer>, Error> {
119+
match with_timeout(DEFAULT_TIMEOUT, self.connect_consumer_no_timeout(capability)).await {
120+
Ok(r) => r,
121+
Err(_) => Err(Error::Timeout),
122+
}
123+
}
124+
125+
/// Connect this device as a provider
126+
pub async fn connect_provider_no_timeout(
127+
self,
128+
capability: PowerCapability,
129+
) -> Result<Policy<'a, ConnectedProvider>, Error> {
130+
self.connect_provider_internal_no_timeout(capability).await?;
131+
Ok(Policy::new(self.device))
132+
}
133+
92134
/// Connect this device as a provider
93135
pub async fn connect_provider(self, capability: PowerCapability) -> Result<Policy<'a, ConnectedProvider>, Error> {
94136
self.connect_provider_internal(capability).await?;
@@ -97,6 +139,12 @@ impl<'a> Policy<'a, Idle> {
97139
}
98140

99141
impl<'a> Policy<'a, ConnectedConsumer> {
142+
/// Disconnect this device
143+
pub async fn disconnect_no_timeout(self) -> Result<Policy<'a, Idle>, Error> {
144+
self.disconnect_internal_no_timeout().await?;
145+
Ok(Policy::new(self.device))
146+
}
147+
100148
/// Disconnect this device
101149
pub async fn disconnect(self) -> Result<Policy<'a, Idle>, Error> {
102150
self.disconnect_internal().await?;
@@ -106,18 +154,36 @@ impl<'a> Policy<'a, ConnectedConsumer> {
106154

107155
impl<'a> Policy<'a, ConnectedProvider> {
108156
/// Disconnect this device
109-
pub async fn disconnect(self) -> Result<Policy<'a, Idle>, Error> {
110-
if let Err(e) = self.disconnect_internal().await {
157+
pub async fn disconnect_no_timeout(self) -> Result<Policy<'a, Idle>, Error> {
158+
if let Err(e) = self.disconnect_internal_no_timeout().await {
111159
error!("Error disconnecting device {}: {:?}", self.device.id().0, e);
112160
self.device.enter_recovery().await;
113161
return Err(e);
114162
}
115163
Ok(Policy::new(self.device))
116164
}
117165

166+
/// Disconnect this device
167+
pub async fn disconnect(self) -> Result<Policy<'a, Idle>, Error> {
168+
match with_timeout(DEFAULT_TIMEOUT, self.disconnect_no_timeout()).await {
169+
Ok(r) => r,
170+
Err(_) => Err(Error::Timeout),
171+
}
172+
}
173+
118174
/// Connect this device as a provider
119-
pub async fn connect_provider(&self, capability: PowerCapability) -> Result<(), Error> {
120-
self.connect_provider_internal(capability).await
175+
pub async fn connect_provider_no_timeout(
176+
&self,
177+
capability: PowerCapability,
178+
) -> Result<Policy<'a, ConnectedProvider>, Error> {
179+
self.connect_provider_internal_no_timeout(capability).await?;
180+
Ok(Policy::new(self.device))
181+
}
182+
183+
/// Connect this device as a provider
184+
pub async fn connect_provider(&self, capability: PowerCapability) -> Result<Policy<'a, ConnectedProvider>, Error> {
185+
self.connect_provider_internal(capability).await?;
186+
Ok(Policy::new(self.device))
121187
}
122188

123189
/// Get the provider power capability of this device

embedded-service/src/power/policy/device.rs

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
use core::ops::DerefMut;
33

44
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
5-
use embassy_sync::channel::Channel;
65
use embassy_sync::mutex::Mutex;
76

87
use super::{action, DeviceId, Error, PowerCapability};
98
use crate::intrusive_list;
9+
use crate::ipc::deferred;
1010

1111
/// Most basic device states
1212
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,7 +63,7 @@ struct InternalState {
6363
/// Data for a device request
6464
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6565
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66-
pub enum RequestData {
66+
pub enum CommandData {
6767
/// Start consuming on this device
6868
ConnectConsumer(PowerCapability),
6969
/// Start providinig on this device
@@ -75,11 +75,11 @@ pub enum RequestData {
7575
/// Request from power policy service to a device
7676
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7777
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
78-
pub struct Request {
78+
pub struct Command {
7979
/// Target device
8080
pub id: DeviceId,
8181
/// Request data
82-
pub data: RequestData,
82+
pub data: CommandData,
8383
}
8484

8585
/// Data for a device response
@@ -110,9 +110,6 @@ pub struct Response {
110110
pub data: ResponseData,
111111
}
112112

113-
/// Channel size for device requests
114-
pub const DEVICE_CHANNEL_SIZE: usize = 1;
115-
116113
/// Device struct
117114
pub struct Device {
118115
/// Intrusive list node
@@ -121,10 +118,8 @@ pub struct Device {
121118
id: DeviceId,
122119
/// Current state of the device
123120
state: Mutex<NoopRawMutex, InternalState>,
124-
/// Channel for requests to the device
125-
request: Channel<NoopRawMutex, RequestData, DEVICE_CHANNEL_SIZE>,
126-
/// Channel for responses from the device
127-
response: Channel<NoopRawMutex, InternalResponseData, DEVICE_CHANNEL_SIZE>,
121+
/// Command channel
122+
command: deferred::Channel<NoopRawMutex, CommandData, InternalResponseData>,
128123
}
129124

130125
impl Device {
@@ -138,8 +133,7 @@ impl Device {
138133
consumer_capability: None,
139134
in_recovery: false,
140135
}),
141-
request: Channel::new(),
142-
response: Channel::new(),
136+
command: deferred::Channel::new(),
143137
}
144138
}
145139

@@ -191,20 +185,14 @@ impl Device {
191185
self.state.lock().await.in_recovery = false;
192186
}
193187

194-
/// Sends a request to this device and returns a response
195-
pub(super) async fn execute_device_request(&self, request: RequestData) -> Result<ResponseData, Error> {
196-
self.request.send(request).await;
197-
self.response.receive().await
198-
}
199-
200-
/// Wait for a request
201-
pub async fn wait_request(&self) -> RequestData {
202-
self.request.receive().await
188+
/// Execute a command on the device
189+
pub(super) async fn execute_device_command(&self, command: CommandData) -> Result<ResponseData, Error> {
190+
self.command.execute(command).await
203191
}
204192

205-
/// Send a response
206-
pub async fn send_response(&self, response: InternalResponseData) {
207-
self.response.send(response).await;
193+
/// Create a handler for the command channel
194+
pub async fn receive(&self) -> deferred::Request<'_, NoopRawMutex, CommandData, InternalResponseData> {
195+
self.command.receive().await
208196
}
209197

210198
/// Internal function to set device state

embedded-service/src/power/policy/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ pub enum Error {
2020
InvalidState(device::StateKind, device::StateKind),
2121
/// Invalid response
2222
InvalidResponse,
23+
/// Timeout
24+
Timeout,
2325
/// Bus error
2426
Bus,
2527
/// Generic failure

0 commit comments

Comments
 (0)