esp_rtos/esp_radio/
mod.rs

1//! esp-radio support
2
3use core::{ffi::c_void, ptr::NonNull};
4
5use allocator_api2::boxed::Box;
6use esp_hal::{
7    system::Cpu,
8    time::{Duration, Instant},
9};
10use esp_radio_rtos_driver::{
11    register_semaphore_implementation,
12    semaphore::{SemaphoreImplementation, SemaphoreKind, SemaphorePtr},
13};
14
15use crate::{
16    SCHEDULER,
17    run_queue::MaxPriority,
18    scheduler::Scheduler,
19    semaphore::Semaphore,
20    task::{self, Task},
21};
22
23mod queue;
24mod timer_queue;
25
26impl esp_radio_rtos_driver::Scheduler for Scheduler {
27    fn initialized(&self) -> bool {
28        self.with(|scheduler| {
29            if scheduler.time_driver.is_none() {
30                warn!("Trying to initialize esp-radio before starting esp-rtos");
31                return false;
32            }
33
34            let current_cpu = Cpu::current() as usize;
35            if !scheduler.per_cpu[current_cpu].initialized {
36                warn!(
37                    "Trying to initialize esp-radio on {:?} but esp-rtos is not running on this core",
38                    current_cpu
39                );
40                return false;
41            }
42
43            true
44        })
45    }
46
47    fn yield_task(&self) {
48        task::yield_task();
49    }
50
51    fn yield_task_from_isr(&self) {
52        task::yield_task();
53    }
54
55    fn max_task_priority(&self) -> u32 {
56        MaxPriority::MAX_PRIORITY as u32
57    }
58
59    fn task_create(
60        &self,
61        name: &str,
62        task: extern "C" fn(*mut c_void),
63        param: *mut c_void,
64        priority: u32,
65        pin_to_core: Option<u32>,
66        task_stack_size: usize,
67    ) -> *mut c_void {
68        self.create_task(
69            name,
70            task,
71            param,
72            task_stack_size,
73            priority.min(self.max_task_priority()),
74            pin_to_core.and_then(|core| match core {
75                0 => Some(Cpu::ProCpu),
76                #[cfg(multi_core)]
77                1 => Some(Cpu::AppCpu),
78                _ => {
79                    warn!("Invalid core number: {}", core);
80                    None
81                }
82            }),
83        )
84        .as_ptr()
85        .cast()
86    }
87
88    fn current_task(&self) -> *mut c_void {
89        self.current_task().as_ptr().cast()
90    }
91
92    fn schedule_task_deletion(&self, task_handle: *mut c_void) {
93        task::schedule_task_deletion(task_handle as *mut Task)
94    }
95
96    fn current_task_thread_semaphore(&self) -> SemaphorePtr {
97        task::with_current_task(|task| {
98            NonNull::from(
99                task.thread_semaphore
100                    .get_or_insert_with(|| Semaphore::new_counting(0, 1)),
101            )
102            .cast()
103        })
104    }
105
106    fn usleep(&self, us: u32) {
107        SCHEDULER.sleep_until(Instant::now() + Duration::from_micros(us as u64));
108    }
109
110    fn now(&self) -> u64 {
111        // We're using a SingleShotTimer as the time driver, which lets us use the system timer's
112        // timestamps.
113        crate::now()
114    }
115}
116
117impl Semaphore {
118    unsafe fn from_ptr<'a>(ptr: SemaphorePtr) -> &'a Self {
119        unsafe { ptr.cast::<Self>().as_ref() }
120    }
121}
122
123impl SemaphoreImplementation for Semaphore {
124    fn create(kind: SemaphoreKind) -> SemaphorePtr {
125        let sem = Box::new(match kind {
126            SemaphoreKind::Counting { max, initial } => Semaphore::new_counting(initial, max),
127            SemaphoreKind::Mutex => Semaphore::new_mutex(false),
128            SemaphoreKind::RecursiveMutex => Semaphore::new_mutex(true),
129        });
130        NonNull::from(Box::leak(sem)).cast()
131    }
132
133    unsafe fn delete(semaphore: SemaphorePtr) {
134        let sem = unsafe { Box::from_raw(semaphore.cast::<Semaphore>().as_ptr()) };
135        core::mem::drop(sem);
136    }
137
138    unsafe fn take(semaphore: SemaphorePtr, timeout_us: Option<u32>) -> bool {
139        let semaphore = unsafe { Semaphore::from_ptr(semaphore) };
140
141        semaphore.take(timeout_us)
142    }
143
144    unsafe fn give(semaphore: SemaphorePtr) -> bool {
145        let semaphore = unsafe { Semaphore::from_ptr(semaphore) };
146
147        semaphore.give()
148    }
149
150    unsafe fn current_count(semaphore: SemaphorePtr) -> u32 {
151        let semaphore = unsafe { Semaphore::from_ptr(semaphore) };
152
153        semaphore.current_count()
154    }
155
156    unsafe fn try_take(semaphore: SemaphorePtr) -> bool {
157        let semaphore = unsafe { Semaphore::from_ptr(semaphore) };
158
159        semaphore.try_take()
160    }
161
162    unsafe fn try_give_from_isr(semaphore: SemaphorePtr, _hptw: Option<&mut bool>) -> bool {
163        unsafe { <Self as SemaphoreImplementation>::give(semaphore) }
164    }
165
166    unsafe fn try_take_from_isr(semaphore: SemaphorePtr, _hptw: Option<&mut bool>) -> bool {
167        unsafe { <Self as SemaphoreImplementation>::try_take(semaphore) }
168    }
169}
170
171register_semaphore_implementation!(Semaphore);