Skip to content

Commit 31fe9f4

Browse files
authored
Merge pull request #81 from jerrysxie/mock-service-example
example: add mock_service example
2 parents 93d169a + ff7efd8 commit 31fe9f4

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
extern crate embedded_services_examples;
5+
6+
use defmt::info;
7+
use embassy_executor::Spawner;
8+
9+
#[derive(Copy, Clone, Debug, defmt::Format)]
10+
enum TxMessage {
11+
UpdateBatteryStatus(u32),
12+
}
13+
14+
#[derive(Copy, Clone, Debug, defmt::Format)]
15+
enum RxMessage {
16+
SetBatteryCharge(u32),
17+
}
18+
19+
// Mock eSPI transport service
20+
mod espi_service {
21+
use crate::{RxMessage, TxMessage};
22+
use core::convert::Infallible;
23+
use defmt::info;
24+
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
25+
use embassy_sync::once_lock::OnceLock;
26+
use embassy_sync::signal::Signal;
27+
use embedded_services::transport::{self, Endpoint, External, Internal};
28+
29+
struct Service {
30+
endpoint: transport::EndpointLink,
31+
32+
// This is can be an Embassy signal or channel or whatever Embassy async notification construct
33+
signal: Signal<NoopRawMutex, TxMessage>,
34+
}
35+
36+
impl Service {
37+
fn new() -> Self {
38+
Service {
39+
endpoint: transport::EndpointLink::uninit(Endpoint::External(External::Host)),
40+
signal: Signal::new(),
41+
}
42+
}
43+
}
44+
45+
impl transport::MessageDelegate for Service {
46+
fn process(&self, message: &transport::Message) {
47+
if let Some(msg) = message.data.get::<TxMessage>() {
48+
self.signal.signal(*msg);
49+
}
50+
}
51+
}
52+
53+
static ESPI_SERVICE: OnceLock<Service> = OnceLock::new();
54+
55+
// Initialize eSPI service and register it with the transport service
56+
pub async fn init() {
57+
let espi_service = ESPI_SERVICE.get_or_init(|| Service::new());
58+
59+
transport::register_endpoint(espi_service, &espi_service.endpoint)
60+
.await
61+
.unwrap();
62+
}
63+
64+
// Funtion to forward a battery_charge_message to the battery service
65+
pub async fn forward_set_battery_charge_message(battery_charge: u32) -> Result<(), Infallible> {
66+
let espi_service = ESPI_SERVICE.get().await;
67+
68+
espi_service
69+
.endpoint
70+
.send(
71+
Endpoint::Internal(Internal::Battery),
72+
&RxMessage::SetBatteryCharge(battery_charge),
73+
)
74+
.await
75+
}
76+
77+
// espi service that will update the memory map
78+
#[embassy_executor::task]
79+
pub async fn espi_service() {
80+
let espi_service = ESPI_SERVICE.get().await;
81+
82+
loop {
83+
let msg = espi_service.signal.wait().await;
84+
85+
match msg {
86+
TxMessage::UpdateBatteryStatus(_) => {
87+
info!("Update battery status in memory map");
88+
embassy_time::Timer::after_secs(1).await;
89+
}
90+
}
91+
}
92+
}
93+
}
94+
95+
// Mock battery service
96+
mod battery_service {
97+
use crate::{RxMessage, TxMessage};
98+
use defmt::info;
99+
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
100+
use embassy_sync::once_lock::OnceLock;
101+
use embassy_sync::signal::Signal;
102+
use embedded_services::transport::{self, Endpoint, External, Internal};
103+
104+
struct Service {
105+
endpoint: transport::EndpointLink,
106+
107+
// This is can be an Embassy signal or channel or whatever Embassy async notification construct
108+
signal: Signal<NoopRawMutex, RxMessage>,
109+
}
110+
111+
impl Service {
112+
fn new() -> Self {
113+
Service {
114+
endpoint: transport::EndpointLink::uninit(Endpoint::Internal(Internal::Battery)),
115+
signal: Signal::new(),
116+
}
117+
}
118+
}
119+
120+
impl transport::MessageDelegate for Service {
121+
fn process(&self, message: &transport::Message) {
122+
if let Some(msg) = message.data.get::<RxMessage>() {
123+
self.signal.signal(*msg);
124+
}
125+
}
126+
}
127+
128+
static BATTERY_SERVICE: OnceLock<Service> = OnceLock::new();
129+
130+
// Initialize battery service
131+
pub async fn init() {
132+
let battery_service = BATTERY_SERVICE.get_or_init(|| Service::new());
133+
134+
transport::register_endpoint(battery_service, &battery_service.endpoint)
135+
.await
136+
.unwrap();
137+
}
138+
139+
// Service to update the battery value in the memory map periodically
140+
#[embassy_executor::task]
141+
pub async fn battery_update_service() {
142+
let battery_service = BATTERY_SERVICE.get().await;
143+
144+
loop {
145+
let battery_status = 0;
146+
battery_service
147+
.endpoint
148+
.send(
149+
Endpoint::External(External::Host),
150+
&TxMessage::UpdateBatteryStatus(battery_status),
151+
)
152+
.await
153+
.unwrap();
154+
info!("Sending updated battery status to espi service");
155+
156+
embassy_time::Timer::after_secs(1).await;
157+
}
158+
}
159+
160+
// Service to receive battery configuration request from the host
161+
#[embassy_executor::task]
162+
pub async fn battery_config_service() {
163+
let battery_service = BATTERY_SERVICE.get().await;
164+
165+
loop {
166+
let msg = battery_service.signal.wait().await;
167+
168+
match msg {
169+
RxMessage::SetBatteryCharge(charge) => {
170+
info!("Set battery charge {}", charge);
171+
}
172+
}
173+
}
174+
}
175+
}
176+
177+
#[embassy_executor::main]
178+
async fn main(spawner: Spawner) {
179+
let _p = embassy_imxrt::init(Default::default());
180+
181+
info!("Platform initialization complete ...");
182+
183+
embedded_services::init().await;
184+
185+
info!("Service initialization complete...");
186+
187+
espi_service::init().await;
188+
battery_service::init().await;
189+
190+
spawner.spawn(espi_service::espi_service()).unwrap();
191+
192+
spawner.spawn(battery_service::battery_update_service()).unwrap();
193+
spawner.spawn(battery_service::battery_config_service()).unwrap();
194+
195+
info!("Subsystem initialization complete...");
196+
197+
// Pretend this loop is an interrupt that fires every second to set the battery charge
198+
let mut battery_charge = 0;
199+
loop {
200+
battery_charge += 1;
201+
embassy_time::Timer::after_secs(1).await;
202+
espi_service::forward_set_battery_charge_message(battery_charge)
203+
.await
204+
.unwrap();
205+
}
206+
}

0 commit comments

Comments
 (0)