Skip to content

Commit 29ded39

Browse files
authored
Add more implementation docs (#4078)
1 parent e15e837 commit 29ded39

File tree

5 files changed

+354
-27
lines changed

5 files changed

+354
-27
lines changed

esp-radio-preempt-driver/src/lib.rs

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,11 @@
1212
//! This crate abstracts the capabilities of FreeRTOS. The scheduler must implement the following
1313
//! capabilities:
1414
//!
15-
//! - A preemptive task scheduler
16-
//! - Mutexes
17-
//! - Semaphores
18-
//! - Queues
19-
//! - Timers (functions that are executed at a specific time)
20-
//!
21-
//! In order to hook up a scheduler, implement the `Scheduler` trait for a struct, and register it
22-
//! using the `scheduler_impl!()` macro. Only one scheduler can be registered in a firmware.
23-
//!
24-
//! Example:
25-
//!
26-
//! ```rust,ignore
27-
//! struct MyScheduler {}
28-
//!
29-
//! impl esp_preempt::Scheduler for MyScheduler {
30-
//! // impl goes here
31-
//! }
32-
//!
33-
//! esp_preempt::scheduler_impl!(static SCHEDULER: MyScheduler = MyScheduler {});
34-
//! ```
15+
//! - A preemptive task scheduler: [`Scheduler`]
16+
//! - Mutexes: [`mutex::MutexImplementation`]
17+
//! - Semaphores: [`semaphore::SemaphoreImplementation`]
18+
//! - Queues: [`queue::QueueImplementation`]
19+
//! - Timers (functions that are executed at a specific time): [`timer::TimerImplementation`]
3520
//!
3621
//! [`esp-preempt`]: https://crates.io/crates/esp-preempt
3722
@@ -170,6 +155,73 @@ macro_rules! scheduler_impl {
170155
///
171156
/// This trait needs to be implemented by a driver crate to integrate esp-radio with a software
172157
/// platform.
158+
///
159+
/// The following snippet demonstrates the boilerplate necessary to implement a scheduler using the
160+
/// `Scheduler` trait:
161+
///
162+
/// ```rust,no_run
163+
/// struct MyScheduler {}
164+
///
165+
/// impl esp_radio_preempt_driver::Scheduler for MyScheduler {
166+
///
167+
/// fn initialized(&self) -> bool {
168+
/// unimplemented!()
169+
/// }
170+
///
171+
/// fn enable(&self) {
172+
/// unimplemented!()
173+
/// }
174+
///
175+
/// fn disable(&self) {
176+
/// unimplemented!()
177+
/// }
178+
///
179+
/// fn yield_task(&self) {
180+
/// unimplemented!()
181+
/// }
182+
///
183+
/// fn yield_task_from_isr(&self) {
184+
/// unimplemented!()
185+
/// }
186+
///
187+
/// fn max_task_priority(&self) -> u32 {
188+
/// unimplemented!()
189+
/// }
190+
///
191+
/// fn task_create(
192+
/// &self,
193+
/// task: extern "C" fn(*mut c_void),
194+
/// param: *mut c_void,
195+
/// priority: u32,
196+
/// pin_to_core: Option<u32>,
197+
/// task_stack_size: usize,
198+
/// ) -> *mut c_void {
199+
/// unimplemented!()
200+
/// }
201+
///
202+
/// fn current_task(&self) -> *mut c_void {
203+
/// unimplemented!()
204+
/// }
205+
///
206+
/// fn schedule_task_deletion(&self, task_handle: *mut c_void) {
207+
/// unimplemented!()
208+
/// }
209+
///
210+
/// fn current_task_thread_semaphore(&self) -> SemaphorePtr {
211+
/// unimplemented!()
212+
/// }
213+
///
214+
/// fn usleep(&self, us: u32) {
215+
/// unimplemented!()
216+
/// }
217+
///
218+
/// fn now(&self) -> u64 {
219+
/// unimplemented!()
220+
/// }
221+
/// }
222+
///
223+
/// esp_radio_preempt_driver::scheduler_impl!(static SCHEDULER: MyScheduler = MyScheduler {});
224+
/// ```
173225
pub trait Scheduler: Send + Sync + 'static {
174226
/// This function is called by `esp_radio::init` to verify that the scheduler is properly set
175227
/// up.

esp-radio-preempt-driver/src/mutex.rs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
//! Mutexes
1+
//! # Mutexes (mutual exclusion)
2+
//!
3+
//! Mutexes are a synchronization primitive used to protect shared data from concurrent access.
4+
//! They allow only one thread at a time to access a critical section of code or data.
5+
//!
6+
//! ## Implementation
7+
//!
8+
//! Implement the `MutexImplementation` trait for an object, and use the
9+
//! `register_mutex_implementation` to register that implementation for esp-radio.
10+
//!
11+
//! See the [`MutexImplementation`] documentation for more information.
12+
//!
13+
//! ## Usage
14+
//!
15+
//! Users should use [`MutexHandle`] to interact with mutexes created by the driver implementation.
16+
//!
17+
//! > Note that the only expected user of this crate is esp-radio.
218
319
use core::ptr::NonNull;
420

@@ -13,8 +29,48 @@ unsafe extern "Rust" {
1329
fn esp_preempt_mutex_unlock(mutex: MutexPtr) -> bool;
1430
}
1531

32+
/// A mutex (mutual exclusion) primitive.
33+
///
34+
/// The following snippet demonstrates the boilerplate necessary to implement a mutex using the
35+
/// `MutexImplementation` trait:
36+
///
37+
/// ```rust,no_run
38+
/// use esp_radio_preempt_driver::{
39+
/// mutex::{MutexImplementation, MutexPtr},
40+
/// register_mutex_implementation,
41+
/// };
42+
///
43+
/// struct MyMutex {
44+
/// // Mutex implementation details
45+
/// }
46+
///
47+
/// impl MutexImplementation for MyMutex {
48+
/// fn create(recursive: bool) -> MutexPtr {
49+
/// unimplemented!()
50+
/// }
51+
///
52+
/// unsafe fn delete(mutex: MutexPtr) {
53+
/// unimplemented!()
54+
/// }
55+
///
56+
/// unsafe fn lock(mutex: MutexPtr, timeout_us: Option<u32>) -> bool {
57+
/// unimplemented!()
58+
/// }
59+
///
60+
/// unsafe fn unlock(mutex: MutexPtr) -> bool {
61+
/// unimplemented!()
62+
/// }
63+
/// }
64+
///
65+
/// register_mutex_implementation!(MyMutex);
66+
/// ```
1667
pub trait MutexImplementation {
1768
/// Creates a new mutex instance.
69+
///
70+
/// The mutex should start in the unlocked state.
71+
///
72+
/// If `recursive` is `true`, the mutex should support recursive locking (i.e. the mutex owner
73+
/// can lock the mutex multiple times).
1874
fn create(recursive: bool) -> MutexPtr;
1975

2076
/// Deletes a mutex instance.
@@ -34,7 +90,7 @@ pub trait MutexImplementation {
3490
///
3591
/// This function returns `true` if the mutex was locked, `false` if the timeout was reached.
3692
///
37-
/// Recursive mutexes can be re-locked by the mutex owner.
93+
/// Recursive mutexes can be re-locked by the mutex owner without blocking.
3894
///
3995
/// # Safety
4096
///
@@ -44,7 +100,8 @@ pub trait MutexImplementation {
44100
/// Unlocks a mutex.
45101
///
46102
/// This function returns `true` if the mutex was unlocked, `false` if the mutex wasn't locked,
47-
/// or the unlocking task was not the mutex owner.
103+
/// or the unlocking task was not the mutex owner. Unlocking a recursive mutex also returns
104+
/// `true` if the mutex's lock counter is successfully decremented.
48105
///
49106
/// Recursive mutexes are released only when `unlock` has been called for each preceding `lock`.
50107
///
@@ -83,6 +140,9 @@ macro_rules! register_mutex_implementation {
83140
};
84141
}
85142

143+
/// Mutex handle.
144+
///
145+
/// This handle is used to interact with mutexes created by the driver implementation.
86146
#[repr(transparent)]
87147
pub struct MutexHandle(MutexPtr);
88148
impl MutexHandle {

esp-radio-preempt-driver/src/queue.rs

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
//! Queues
1+
//! # Queues
2+
//!
3+
//! Queues are a synchronization primitive used to communicate between tasks.
4+
//! They allow tasks to send and receive data in a first-in-first-out (FIFO) manner.
5+
//!
6+
//! ## Implementation
7+
//!
8+
//! Implement the `QueueImplementation` trait for an object, and use the
9+
//! `register_queue_implementation` to register that implementation for esp-radio.
10+
//!
11+
//! See the [`QueueImplementation`] documentation for more information.
12+
//!
13+
//! ## Usage
14+
//!
15+
//! Users should use [`QueueHandle`] to interact with queues created by the driver implementation.
16+
//!
17+
//! > Note that the only expected user of this crate is esp-radio.
218
319
use core::ptr::NonNull;
420

@@ -34,8 +50,73 @@ unsafe extern "Rust" {
3450
fn esp_preempt_queue_messages_waiting(queue: QueuePtr) -> usize;
3551
}
3652

53+
/// A queue primitive.
54+
///
55+
/// The following snippet demonstrates the boilerplate necessary to implement a queue using the
56+
/// `QueueImplementation` trait:
57+
///
58+
/// ```rust,no_run
59+
/// use esp_radio_preempt_driver::{
60+
/// queue::{QueueImplementation, QueuePtr},
61+
/// register_queue_implementation,
62+
/// };
63+
///
64+
/// struct MyQueue {
65+
/// // Queue implementation details
66+
/// }
67+
///
68+
/// impl QueueImplementation for MyQueue {
69+
/// fn create(capacity: usize, item_size: usize) -> QueuePtr {
70+
/// unimplemented!()
71+
/// }
72+
///
73+
/// unsafe fn delete(queue: QueuePtr) {
74+
/// unimplemented!()
75+
/// }
76+
///
77+
/// unsafe fn send_to_front(queue: QueuePtr, item: *const u8, timeout_us: Option<u32>) -> bool {
78+
/// unimplemented!()
79+
/// }
80+
///
81+
/// unsafe fn send_to_back(queue: QueuePtr, item: *const u8, timeout_us: Option<u32>) -> bool {
82+
/// unimplemented!()
83+
/// }
84+
///
85+
/// unsafe fn try_send_to_back_from_isr(
86+
/// queue: QueuePtr,
87+
/// item: *const u8,
88+
/// higher_prio_task_waken: Option<&mut bool>,
89+
/// ) -> bool {
90+
/// unimplemented!()
91+
/// }
92+
///
93+
/// unsafe fn receive(queue: QueuePtr, item: *mut u8, timeout_us: Option<u32>) -> bool {
94+
/// unimplemented!()
95+
/// }
96+
///
97+
/// unsafe fn try_receive_from_isr(
98+
/// queue: QueuePtr,
99+
/// item: *mut u8,
100+
/// higher_prio_task_waken: Option<&mut bool>,
101+
/// ) -> bool {
102+
/// unimplemented!()
103+
/// }
104+
///
105+
/// unsafe fn remove(queue: QueuePtr, item: *const u8) {
106+
/// unimplemented!()
107+
/// }
108+
///
109+
/// fn messages_waiting(queue: QueuePtr) -> usize {
110+
/// unimplemented!()
111+
/// }
112+
/// }
113+
///
114+
/// register_queue_implementation!(MyQueue);
115+
/// ```
37116
pub trait QueueImplementation {
38-
/// Creates a new queue instance.
117+
/// Creates a new, empty queue instance.
118+
///
119+
/// The queue must have a capacity for `capacity` number of `item_size` byte items.
39120
fn create(capacity: usize, item_size: usize) -> QueuePtr;
40121

41122
/// Deletes a queue instance.
@@ -227,6 +308,9 @@ macro_rules! register_queue_implementation {
227308
};
228309
}
229310

311+
/// Queue handle.
312+
///
313+
/// This handle is used to interact with queues created by the driver implementation.
230314
#[repr(transparent)]
231315
pub struct QueueHandle(QueuePtr);
232316
impl QueueHandle {

0 commit comments

Comments
 (0)