Skip to content

Commit 3577b9d

Browse files
authored
Reimplement IPCs using WaitQueue (#4559)
* Use driver API for thread semaphore * Update scheduler related naming * Add ThreadPtr * Hide CompatQueue behind feature, remove impl from esp-rtos * Replace CompatQueue's mutex with esp-sync * Deduplicate/fix queue operations * Also hide CompatTimer * Re-add logging to CompatTimer * Create timer thread when initializing the queue * Pull set_priority up into the scheduler * Replace Mutex in CompatTimer with esp-sync * Add WaitQueue, move radio Semaphore impl * Remove esp_rtos semaphore * Fix up changelog * Assert that there are no tasks waiting when queue is dropped * Update NPL glue code * Fix clippy * Remove redundant pointer write * Hide WaitQueue behind esp-radio feature for now
1 parent 3f7456c commit 3577b9d

File tree

24 files changed

+1936
-1517
lines changed

24 files changed

+1936
-1517
lines changed

esp-radio-rtos-driver/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- `SemaphoreHandle::take_with_deadline` to take a semaphore with a deadline. (#4555)
1414
- `QueueHandle::{send_to_front_with_deadline, send_to_back_with_deadline, receive_with_deadline}` for queue operations with a deadline. (#4555)
1515
- `timer::CompatTimer` to simplify OS integration. (#4555)
16+
- `semaphore::CompatSemaphore` to simplify OS integration. (#4559)
17+
- `wait_queue::WaitQueueImplementation` as an alternative way to integrate with an OS. (#4559)
18+
- `ThreadPtr` (#4559)
19+
- The `ipc-implementations` feature, which enables the `CompatQueue`, `CompatSemaphore` and `CompatTimer` types (#4559)
20+
- Chip-specific features required for the `ipc-implementations` feature (#4559)
1621

1722
### Changed
1823

24+
- Renamed `Scheduler` to `SchedulerImplementation` and `scheduler_impl!` to `register_scheduler_implementation!` (#4559)
25+
- `current_task`, `task_create` and `schedule_task_deletion` functions now work with `ThreadPtr` instead of `*mut c_void` (#4559)
26+
- `schedule_task_deletion` now takes an `Option` (#4559)
1927

2028
### Fixed
2129

30+
- `register_queue_implementation` no longer requires `QueuePtr` to be in scope (#4559)
2231

2332
### Removed
2433

esp-radio-rtos-driver/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,26 @@ portable-atomic = "1"
2121

2222
[target."cfg(not(target_has_atomic = \"32\"))".dependencies]
2323
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }
24+
25+
[dependencies]
26+
esp-sync = { version = "0.1.1", path = "../esp-sync", optional = true }
27+
cfg-if = "1"
28+
29+
# Logging interfaces, they are mutually exclusive so they need to be behind separate features.
30+
defmt = { version = "1.0", optional = true }
31+
log-04 = { package = "log", version = "0.4", optional = true }
32+
33+
[features]
34+
ipc-implementations = ["esp-sync"]
35+
# One of the following features must be enabled to select the target chip, if the `ipc-implementations` feature is enabled.
36+
esp32 = ["esp-sync?/esp32"]
37+
esp32c2 = ["esp-sync?/esp32c2"]
38+
esp32c3 = ["esp-sync?/esp32c3"]
39+
esp32c6 = ["esp-sync?/esp32c6"]
40+
esp32h2 = ["esp-sync?/esp32h2"]
41+
esp32s2 = ["esp-sync?/esp32s2"]
42+
esp32s3 = ["esp-sync?/esp32s3"]
43+
44+
# Logging Feature Flags
45+
log-04 = ["dep:log-04"]
46+
defmt = ["dep:defmt"]

esp-radio-rtos-driver/src/fmt.rs

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
#![macro_use]
2+
#![allow(unused_macros)]
3+
4+
use core::fmt::{Debug, Display, LowerHex};
5+
6+
#[collapse_debuginfo(yes)]
7+
macro_rules! assert {
8+
($($x:tt)*) => {
9+
{
10+
cfg_if::cfg_if! {
11+
if #[cfg(feature = "defmt")] {
12+
::defmt::assert!($($x)*);
13+
} else {
14+
::core::assert!($($x)*);
15+
}
16+
}
17+
}
18+
};
19+
}
20+
21+
#[collapse_debuginfo(yes)]
22+
macro_rules! assert_eq {
23+
($($x:tt)*) => {
24+
{
25+
cfg_if::cfg_if! {
26+
if #[cfg(feature = "defmt")] {
27+
::defmt::assert_eq!($($x)*);
28+
} else {
29+
::core::assert_eq!($($x)*);
30+
}
31+
}
32+
}
33+
};
34+
}
35+
36+
#[collapse_debuginfo(yes)]
37+
macro_rules! assert_ne {
38+
($($x:tt)*) => {
39+
{
40+
cfg_if::cfg_if! {
41+
if #[cfg(feature = "defmt")] {
42+
::defmt::assert_ne!($($x)*);
43+
} else {
44+
::core::assert_ne!($($x)*);
45+
}
46+
}
47+
}
48+
};
49+
}
50+
51+
#[collapse_debuginfo(yes)]
52+
macro_rules! debug_assert {
53+
($($x:tt)*) => {
54+
{
55+
cfg_if::cfg_if! {
56+
if #[cfg(feature = "defmt")] {
57+
::defmt::debug_assert!($($x)*);
58+
} else {
59+
::core::debug_assert!($($x)*);
60+
}
61+
}
62+
}
63+
};
64+
}
65+
66+
#[collapse_debuginfo(yes)]
67+
macro_rules! debug_assert_eq {
68+
($($x:tt)*) => {
69+
{
70+
cfg_if::cfg_if! {
71+
if #[cfg(feature = "defmt")] {
72+
::defmt::debug_assert_eq!($($x)*);
73+
} else {
74+
::core::debug_assert_eq!($($x)*);
75+
}
76+
}
77+
}
78+
};
79+
}
80+
81+
#[collapse_debuginfo(yes)]
82+
macro_rules! debug_assert_ne {
83+
($($x:tt)*) => {
84+
{
85+
cfg_if::cfg_if! {
86+
if #[cfg(feature = "defmt")] {
87+
::defmt::debug_assert_ne!($($x)*);
88+
} else {
89+
::core::debug_assert_ne!($($x)*);
90+
}
91+
}
92+
}
93+
};
94+
}
95+
96+
#[collapse_debuginfo(yes)]
97+
macro_rules! todo {
98+
($($x:tt)*) => {
99+
{
100+
cfg_if::cfg_if! {
101+
if #[cfg(feature = "defmt")] {
102+
::defmt::todo!($($x)*);
103+
} else {
104+
::core::todo!($($x)*);
105+
}
106+
}
107+
}
108+
};
109+
}
110+
111+
#[collapse_debuginfo(yes)]
112+
macro_rules! unreachable {
113+
($($x:tt)*) => {
114+
{
115+
cfg_if::cfg_if! {
116+
if #[cfg(feature = "defmt")] {
117+
::defmt::unreachable!($($x)*);
118+
} else {
119+
::core::unreachable!($($x)*);
120+
}
121+
}
122+
}
123+
};
124+
}
125+
126+
#[collapse_debuginfo(yes)]
127+
macro_rules! panic {
128+
($($x:tt)*) => {
129+
{
130+
cfg_if::cfg_if! {
131+
if #[cfg(feature = "defmt")] {
132+
::defmt::panic!($($x)*);
133+
} else {
134+
::core::panic!($($x)*);
135+
}
136+
}
137+
}
138+
};
139+
}
140+
141+
#[collapse_debuginfo(yes)]
142+
macro_rules! trace {
143+
($s:literal $(, $x:expr)* $(,)?) => {
144+
{
145+
cfg_if::cfg_if! {
146+
if #[cfg(feature = "defmt")] {
147+
::defmt::trace!($s $(, $x)*);
148+
} else if #[cfg(feature = "log-04")] {
149+
::log_04::trace!($s $(, $x)*);
150+
} else {
151+
let _ = ($( & $x ),*);
152+
}
153+
}
154+
}
155+
};
156+
}
157+
158+
#[collapse_debuginfo(yes)]
159+
macro_rules! debug {
160+
($s:literal $(, $x:expr)* $(,)?) => {
161+
{
162+
cfg_if::cfg_if! {
163+
if #[cfg(feature = "defmt")] {
164+
::defmt::debug!($s $(, $x)*);
165+
} else if #[cfg(feature = "log-04")] {
166+
::log_04::debug!($s $(, $x)*);
167+
} else {
168+
let _ = ($( & $x ),*);
169+
}
170+
}
171+
}
172+
};
173+
}
174+
175+
#[collapse_debuginfo(yes)]
176+
macro_rules! info {
177+
($s:literal $(, $x:expr)* $(,)?) => {
178+
{
179+
cfg_if::cfg_if! {
180+
if #[cfg(feature = "defmt")] {
181+
::defmt::info!($s $(, $x)*);
182+
} else if #[cfg(feature = "log-04")] {
183+
::log_04::info!($s $(, $x)*);
184+
} else {
185+
let _ = ($( & $x ),*);
186+
}
187+
}
188+
}
189+
};
190+
}
191+
192+
#[collapse_debuginfo(yes)]
193+
macro_rules! warn {
194+
($s:literal $(, $x:expr)* $(,)?) => {
195+
{
196+
cfg_if::cfg_if! {
197+
if #[cfg(feature = "defmt")] {
198+
::defmt::warn!($s $(, $x)*);
199+
} else if #[cfg(feature = "log-04")] {
200+
::log_04::warn!($s $(, $x)*);
201+
} else {
202+
let _ = ($( & $x ),*);
203+
}
204+
}
205+
}
206+
};
207+
}
208+
209+
#[collapse_debuginfo(yes)]
210+
macro_rules! error {
211+
($s:literal $(, $x:expr)* $(,)?) => {
212+
{
213+
cfg_if::cfg_if! {
214+
if #[cfg(feature = "defmt")] {
215+
::defmt::error!($s $(, $x)*);
216+
} else if #[cfg(feature = "log-04")] {
217+
::log_04::error!($s $(, $x)*);
218+
} else {
219+
let _ = ($( & $x ),*);
220+
}
221+
}
222+
}
223+
};
224+
}
225+
226+
#[cfg(feature = "defmt")]
227+
#[collapse_debuginfo(yes)]
228+
macro_rules! unwrap {
229+
($($x:tt)*) => {
230+
::defmt::unwrap!($($x)*)
231+
};
232+
}
233+
234+
#[cold]
235+
#[inline(never)]
236+
#[cfg(not(feature = "defmt"))]
237+
pub(crate) fn __unwrap_failed(arg: &str, e: impl ::core::fmt::Debug) -> ! {
238+
::core::panic!("unwrap of `{}` failed: {:?}", arg, e);
239+
}
240+
241+
#[cold]
242+
#[inline(never)]
243+
#[cfg(not(feature = "defmt"))]
244+
pub(crate) fn __unwrap_failed_with_message(
245+
arg: &str,
246+
e: impl core::fmt::Debug,
247+
msg: impl core::fmt::Display,
248+
) -> ! {
249+
::core::panic!("unwrap of `{}` failed: {}: {:?}", arg, msg, e);
250+
}
251+
252+
#[cfg(not(feature = "defmt"))]
253+
#[collapse_debuginfo(yes)]
254+
macro_rules! unwrap {
255+
($arg:expr) => {
256+
match $crate::fmt::Try::into_result($arg) {
257+
::core::result::Result::Ok(t) => t,
258+
::core::result::Result::Err(e) => { $crate::fmt::__unwrap_failed(::core::stringify!($arg), e) }
259+
}
260+
};
261+
($arg:expr, $msg:expr) => {
262+
match $crate::fmt::Try::into_result($arg) {
263+
::core::result::Result::Ok(t) => t,
264+
::core::result::Result::Err(e) => { $crate::fmt::__unwrap_failed_with_message(::core::stringify!($arg), e, $msg) }
265+
}
266+
};
267+
($arg:expr, $($msg:expr),+ $(,)? ) => {
268+
match $crate::fmt::Try::into_result($arg) {
269+
::core::result::Result::Ok(t) => t,
270+
::core::result::Result::Err(e) => { $crate::fmt::__unwrap_failed_with_message(::core::stringify!($arg), e, ::core::format_args!($($msg,)*)) }
271+
}
272+
}
273+
}
274+
275+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
276+
pub struct NoneError;
277+
278+
pub trait Try {
279+
type Ok;
280+
type Error;
281+
#[allow(unused)]
282+
fn into_result(self) -> Result<Self::Ok, Self::Error>;
283+
}
284+
285+
impl<T> Try for Option<T> {
286+
type Ok = T;
287+
type Error = NoneError;
288+
289+
#[inline]
290+
fn into_result(self) -> Result<T, NoneError> {
291+
self.ok_or(NoneError)
292+
}
293+
}
294+
295+
impl<T, E> Try for Result<T, E> {
296+
type Ok = T;
297+
type Error = E;
298+
299+
#[inline]
300+
fn into_result(self) -> Self {
301+
self
302+
}
303+
}
304+
305+
/// A way to `{:x?}` format a byte slice which is compatible with `defmt`
306+
#[allow(unused)]
307+
pub(crate) struct Bytes<'a>(pub &'a [u8]);
308+
309+
impl Debug for Bytes<'_> {
310+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
311+
write!(f, "{:#02x?}", self.0)
312+
}
313+
}
314+
315+
impl Display for Bytes<'_> {
316+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
317+
write!(f, "{:#02x?}", self.0)
318+
}
319+
}
320+
321+
impl LowerHex for Bytes<'_> {
322+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
323+
write!(f, "{:#02x?}", self.0)
324+
}
325+
}
326+
327+
#[cfg(feature = "defmt")]
328+
impl defmt::Format for Bytes<'_> {
329+
fn format(&self, fmt: defmt::Formatter<'_>) {
330+
defmt::write!(fmt, "{:02x}", self.0)
331+
}
332+
}

0 commit comments

Comments
 (0)