Skip to content

Commit 2b76346

Browse files
committed
refactor CFU to use deferred IPC channel
This is a BREAKING CHANGE which updates embedded-service::cfu's CfuDevice from utilizing a dual-channel model for communication to a deferred IPC channel. Cfu-service, type-c service and the examples were updated to reflect this change.
1 parent 9acbcc2 commit 2b76346

File tree

6 files changed

+140
-215
lines changed

6 files changed

+140
-215
lines changed

cfu-service/src/lib.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,16 @@ impl CfuClient {
2828
tp: comms::Endpoint::uninit(comms::EndpointID::Internal(comms::Internal::Nonvol)),
2929
})
3030
}
31-
pub async fn process_request(&self) -> Result<(), CfuError> {
32-
let request = self.context.wait_request().await;
31+
pub async fn process_request(&self) -> InternalResponse {
32+
let request = self.context.receive().await;
3333
//let device = self.context.get_device(request.id).await?;
34-
let comp = request.id;
34+
let comp = request.command.id;
3535

36-
match request.data {
36+
match request.command.data {
3737
RequestData::FwVersionRequest => {
3838
info!("Received FwVersionRequest, comp {}", comp);
3939
if let Ok(device) = self.context.get_device(comp).await {
40-
let resp = device
41-
.execute_device_request(request.data)
42-
.await
43-
.map_err(CfuError::ProtocolError)?;
40+
let resp = device.execute_device_request(request.command).await?;
4441

4542
// TODO replace with signal to component to get its own fw version
4643
//cfu::send_request(comp, RequestData::FwVersionRequest).await?;
@@ -54,15 +51,18 @@ impl CfuClient {
5451
return Err(CfuError::ProtocolError(CfuProtocolError::BadResponse));
5552
}
5653
}
57-
self.context.send_response(resp).await;
58-
return Ok(());
54+
return Ok(resp);
5955
}
6056
Err(CfuError::InvalidComponent)
6157
}
62-
RequestData::GiveContent(_content_cmd) => Ok(()),
63-
RequestData::GiveOffer(_offer_cmd) => Ok(()),
64-
RequestData::PrepareComponentForUpdate => Ok(()),
65-
RequestData::FinalizeUpdate => Ok(()),
58+
RequestData::GiveContent(_content_cmd) => {
59+
Ok(InternalResponseData::ContentResponse(FwUpdateContentResponse::default()))
60+
}
61+
RequestData::GiveOffer(_offer_cmd) => {
62+
Ok(InternalResponseData::OfferResponse(FwUpdateOfferResponse::default()))
63+
}
64+
RequestData::PrepareComponentForUpdate => Ok(InternalResponseData::ComponentPrepared),
65+
RequestData::FinalizeUpdate => Ok(InternalResponseData::ComponentPrepared),
6666
}
6767
}
6868
}

embedded-service/src/cfu/component.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
use core::future::Future;
33

44
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
5-
use embassy_sync::channel::Channel;
65
use embassy_sync::mutex::Mutex;
76
use embedded_cfu_protocol::components::{CfuComponentInfo, CfuComponentStorage, CfuComponentTraits};
87
use embedded_cfu_protocol::protocol_definitions::*;
@@ -12,6 +11,7 @@ use heapless::Vec;
1211
use super::CfuError;
1312
use crate::cfu::route_request;
1413
use crate::intrusive_list;
14+
use crate::ipc::deferred;
1515

1616
/// Component internal update state
1717
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -57,6 +57,16 @@ impl Default for InternalState {
5757
}
5858
}
5959

60+
/// Request to the cfu service
61+
#[derive(Debug, PartialEq)]
62+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63+
pub struct Request {
64+
/// Component that sent this request
65+
pub id: ComponentId,
66+
/// Request data
67+
pub data: RequestData,
68+
}
69+
6070
/// CFU Request types and necessary data
6171
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6272
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -93,17 +103,16 @@ pub enum InternalResponseData {
93103
ComponentPrepared,
94104
}
95105

96-
/// Channel size for device requests
97-
pub const DEVICE_CHANNEL_SIZE: usize = 1;
106+
/// Wrapper type to make code cleaner
107+
pub type InternalResponse = Result<InternalResponseData, CfuError>;
98108

99109
/// CfuDevice struct
100110
/// Can be inserted in an intrusive-list+
101111
pub struct CfuDevice {
102112
node: intrusive_list::Node,
103113
component_id: ComponentId,
104114
state: Mutex<NoopRawMutex, InternalState>,
105-
request: Channel<NoopRawMutex, RequestData, DEVICE_CHANNEL_SIZE>,
106-
response: Channel<NoopRawMutex, InternalResponseData, DEVICE_CHANNEL_SIZE>,
115+
request: deferred::Channel<NoopRawMutex, Request, InternalResponse>,
107116
}
108117

109118
impl intrusive_list::NodeContainer for CfuDevice {
@@ -124,15 +133,17 @@ impl CfuDeviceContainer for CfuDevice {
124133
}
125134
}
126135

136+
/// Convenience type for CFU request
137+
pub type CfuRequest<'a> = deferred::Request<'a, NoopRawMutex, Request, InternalResponse>;
138+
127139
impl CfuDevice {
128140
/// Constructor for CfuDevice
129141
pub fn new(component_id: ComponentId) -> Self {
130142
Self {
131143
node: intrusive_list::Node::uninit(),
132144
component_id,
133145
state: Mutex::new(InternalState::default()),
134-
request: Channel::new(),
135-
response: Channel::new(),
146+
request: deferred::Channel::new(),
136147
}
137148
}
138149
/// Getter for component id
@@ -151,19 +162,13 @@ impl CfuDevice {
151162
}
152163

153164
/// Sends a request to this device and returns a response
154-
pub async fn execute_device_request(&self, request: RequestData) -> Result<InternalResponseData, CfuProtocolError> {
155-
self.send_request(request).await;
156-
Ok(self.wait_response().await)
157-
}
158-
159-
/// Wait for a request
160-
pub async fn wait_request(&self) -> RequestData {
161-
self.request.receive().await
165+
pub async fn execute_device_request(&self, request: Request) -> InternalResponse {
166+
self.request.execute(request).await
162167
}
163168

164169
/// Send a response
165-
pub async fn send_response(&self, response: InternalResponseData) {
166-
self.response.send(response).await;
170+
pub async fn receive(&self) -> CfuRequest {
171+
self.request.receive().await
167172
}
168173

169174
/// Waits for a response
@@ -213,7 +218,8 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
213218
}
214219
/// wait for a request and process it
215220
pub async fn process_request(&self) -> Result<(), CfuError> {
216-
match self.device.wait_request().await {
221+
let request = self.device.receive().await;
222+
match request.command.data {
217223
RequestData::FwVersionRequest => {
218224
let fwv = self.get_fw_version().await.map_err(CfuError::ProtocolError)?;
219225
let dev_inf = FwVerComponentInfo::new(fwv, self.get_component_id());
@@ -250,9 +256,7 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
250256
),
251257
component_info: comp_info,
252258
};
253-
self.device
254-
.send_response(InternalResponseData::FwVersionResponse(resp))
255-
.await;
259+
request.respond(Ok(InternalResponseData::FwVersionResponse(resp)));
256260
}
257261
RequestData::PrepareComponentForUpdate => {
258262
self.storage_prepare()
@@ -263,9 +267,7 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
263267
// accept any and all offers regardless of what version it is
264268
if buf.component_info.component_id == self.get_component_id() {
265269
let resp = FwUpdateOfferResponse::new_accept(HostToken::Driver);
266-
self.device
267-
.send_response(InternalResponseData::OfferResponse(resp))
268-
.await;
270+
request.respond(Ok(InternalResponseData::OfferResponse(resp)));
269271
}
270272
}
271273
RequestData::GiveContent(buf) => {
@@ -276,8 +278,14 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
276278
.cfu_write(Some(offset), &buf.data)
277279
.await
278280
.map_err(|e| CfuError::ProtocolError(CfuProtocolError::WriterError(e)))?;
281+
request.respond(Ok(InternalResponseData::ContentResponse(FwUpdateContentResponse::new(
282+
buf.header.sequence_num,
283+
CfuUpdateContentResponseStatus::Success,
284+
))));
285+
}
286+
RequestData::FinalizeUpdate => {
287+
request.respond(Ok(InternalResponseData::ComponentPrepared));
279288
}
280-
RequestData::FinalizeUpdate => {}
281289
}
282290
Ok(())
283291
}

embedded-service/src/cfu/mod.rs

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ pub mod component;
55
use core::sync::atomic::{AtomicBool, Ordering};
66

77
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
8-
use embassy_sync::channel::Channel;
98
use embassy_sync::once_lock::OnceLock;
109
use embedded_cfu_protocol::protocol_definitions::{CfuProtocolError, ComponentId};
1110

12-
use crate::cfu::component::{CfuDevice, CfuDeviceContainer, InternalResponseData, RequestData, DEVICE_CHANNEL_SIZE};
11+
use crate::cfu::component::{CfuDevice, CfuDeviceContainer, CfuRequest, InternalResponse, Request, RequestData};
12+
use crate::ipc::deferred;
1313
use crate::{error, intrusive_list};
1414

1515
/// Error type
@@ -24,34 +24,23 @@ pub enum CfuError {
2424
ComponentBusy,
2525
/// Component encountered a protocol error during execution
2626
ProtocolError(CfuProtocolError),
27-
}
28-
29-
/// Request to the power policy service
30-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31-
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32-
pub struct Request {
33-
/// Component that sent this request
34-
pub id: ComponentId,
35-
/// Request data
36-
pub data: RequestData,
27+
/// Timeout occurred while waiting for a response
28+
Timeout,
3729
}
3830

3931
/// Cfu context
4032
struct ClientContext {
4133
/// Registered devices
4234
devices: intrusive_list::IntrusiveList,
4335
/// Request to components
44-
request: Channel<NoopRawMutex, Request, { DEVICE_CHANNEL_SIZE }>,
45-
/// Response from components
46-
response: Channel<NoopRawMutex, InternalResponseData, { DEVICE_CHANNEL_SIZE }>,
36+
request: deferred::Channel<NoopRawMutex, Request, InternalResponse>,
4737
}
4838

4939
impl ClientContext {
5040
fn new() -> Self {
5141
Self {
5242
devices: intrusive_list::IntrusiveList::new(),
53-
request: Channel::new(),
54-
response: Channel::new(),
43+
request: deferred::Channel::new(),
5544
}
5645
}
5746
}
@@ -89,29 +78,27 @@ async fn get_device(id: ComponentId) -> Option<&'static CfuDevice> {
8978
}
9079

9180
/// Convenience function to send a request to the Cfu service
92-
pub async fn send_request(from: ComponentId, request: RequestData) -> Result<InternalResponseData, CfuError> {
81+
pub async fn send_request(from: ComponentId, request: RequestData) -> InternalResponse {
9382
let context = CONTEXT.get().await;
9483
context
9584
.request
96-
.send(Request {
85+
.execute(Request {
9786
id: from,
9887
data: request,
9988
})
100-
.await;
101-
Ok(context.response.receive().await)
89+
.await
10290
}
10391

10492
/// Convenience function to route a request to a specific component
105-
pub async fn route_request(to: ComponentId, request: RequestData) -> Result<InternalResponseData, CfuError> {
93+
pub async fn route_request(to: ComponentId, request: RequestData) -> InternalResponse {
10694
let device = get_device(to).await;
10795
if device.is_none() {
10896
return Err(CfuError::InvalidComponent);
10997
}
11098
device
11199
.unwrap()
112-
.execute_device_request(request)
100+
.execute_device_request(Request { id: to, data: request })
113101
.await
114-
.map_err(CfuError::ProtocolError)
115102
}
116103

117104
/// Send a request to the specific CFU device, but don't wait for a response
@@ -148,14 +135,9 @@ impl ContextToken {
148135
Some(ContextToken(()))
149136
}
150137

151-
/// Wait for a cfu request
152-
pub async fn wait_request(&self) -> Request {
153-
CONTEXT.get().await.request.receive().await
154-
}
155-
156138
/// Send a response to a cfu request
157-
pub async fn send_response(&self, response: InternalResponseData) {
158-
CONTEXT.get().await.response.send(response).await
139+
pub async fn receive(&self) -> CfuRequest {
140+
CONTEXT.get().await.request.receive().await
159141
}
160142

161143
/// Get a device by its ID

0 commit comments

Comments
 (0)