esp_radio/
common_adapter.rs

1#![allow(dead_code)]
2
3use crate::{
4    compat::{common::*, semaphore::*},
5    hal::{self, ram},
6    sys::{
7        c_types::{c_char, c_int, c_ulong, c_void},
8        include::{esp_event_base_t, timeval},
9    },
10    time::blob_ticks_to_micros,
11};
12
13#[ram]
14#[cfg(any(feature = "coex", all(feature = "ble", bt_controller = "btdm")))]
15pub(crate) unsafe extern "C" fn is_in_isr() -> i32 {
16    !hal::interrupt::RunLevel::current().is_thread() as i32
17}
18
19/// **************************************************************************
20/// Name: esp_semphr_create
21///
22/// Description:
23///   Create and initialize semaphore
24///
25/// Input Parameters:
26///   max  - No mean
27///   init - semaphore initialization value
28///
29/// Returned Value:
30///   Semaphore data pointer
31///
32/// *************************************************************************
33#[allow(unused)]
34pub unsafe extern "C" fn semphr_create(max: u32, init: u32) -> *mut c_void {
35    trace!("semphr_create - max {} init {}", max, init);
36    sem_create(max, init)
37}
38
39/// **************************************************************************
40/// Name: esp_semphr_delete
41///
42/// Description:
43///   Delete semaphore
44///
45/// Input Parameters:
46///   semphr - Semaphore data pointer
47///
48/// Returned Value:
49///   None
50///
51/// *************************************************************************
52#[allow(unused)]
53pub unsafe extern "C" fn semphr_delete(semphr: *mut c_void) {
54    trace!("semphr_delete {:?}", semphr);
55    sem_delete(semphr);
56}
57
58/// **************************************************************************
59/// Name: esp_semphr_take
60///
61/// Description:
62///   Wait semaphore within a certain period of time
63///
64/// Input Parameters:
65///   semphr - Semaphore data pointer
66///   ticks  - Wait system ticks
67///
68/// Returned Value:
69///   True if success or false if fail
70///
71/// *************************************************************************
72#[ram]
73pub unsafe extern "C" fn semphr_take(semphr: *mut c_void, tick: u32) -> i32 {
74    trace!(">>>> semphr_take {:?} block_time_tick {}", semphr, tick);
75    sem_take(semphr, blob_ticks_to_micros(tick))
76}
77
78#[ram]
79pub unsafe extern "C" fn semphr_take_from_isr(
80    semphr: *mut c_void,
81    higher_priority_task_waken: *mut bool,
82) -> i32 {
83    trace!(">>>> semphr_take_from_isr {:?}", semphr);
84    sem_try_take_from_isr(semphr, higher_priority_task_waken)
85}
86
87/// **************************************************************************
88/// Name: esp_semphr_give
89///
90/// Description:
91///   Post semaphore
92///
93/// Input Parameters:
94///   semphr - Semaphore data pointer
95///
96/// Returned Value:
97///   True if success or false if fail
98///
99/// *************************************************************************
100#[ram]
101pub unsafe extern "C" fn semphr_give(semphr: *mut c_void) -> i32 {
102    trace!(">>>> semphr_give {:?}", semphr);
103    sem_give(semphr)
104}
105
106#[ram]
107pub unsafe extern "C" fn semphr_give_from_isr(
108    semphr: *mut c_void,
109    higher_priority_task_waken: *mut bool,
110) -> i32 {
111    trace!(">>>> semphr_give_from_isr {:?}", semphr);
112    sem_try_give_from_isr(semphr, higher_priority_task_waken)
113}
114
115/// **************************************************************************
116/// Name: esp_random_ulong
117/// *************************************************************************
118#[allow(unused)]
119#[ram]
120pub unsafe extern "C" fn random() -> c_ulong {
121    trace!("random");
122
123    let rng = hal::rng::Rng::new();
124    rng.random()
125}
126
127/// **************************************************************************
128/// Name: esp_wifi_read_mac
129///
130/// Description:
131///   Read MAC address from efuse
132///
133/// Input Parameters:
134///   mac  - MAC address buffer pointer
135///   type - MAC address type
136///
137/// Returned Value:
138///   0 if success or -1 if fail
139///
140/// *************************************************************************
141pub unsafe extern "C" fn read_mac(mac: *mut u8, type_: u32) -> c_int {
142    trace!("read_mac {:?} {}", mac, type_);
143    use hal::efuse::InterfaceMacAddress;
144
145    let kind = match type_ {
146        #[cfg(soc_has_wifi)]
147        0 => InterfaceMacAddress::Station,
148        #[cfg(soc_has_wifi)]
149        1 => InterfaceMacAddress::AccessPoint,
150        #[cfg(soc_has_bt)]
151        2 => InterfaceMacAddress::Bluetooth,
152        _ => {
153            warn!(
154                "Invalid interface type: {} (expected 0=STA, 1=AP, 2=BT)",
155                type_
156            );
157            return -1;
158        }
159    };
160
161    let addr = hal::efuse::interface_mac_address(kind);
162
163    unsafe {
164        core::ptr::copy_nonoverlapping(addr.as_bytes().as_ptr(), mac, 6);
165    }
166
167    0
168}
169
170// other functions
171#[unsafe(no_mangle)]
172pub unsafe extern "C" fn __esp_radio_puts(s: *const c_char) {
173    unsafe {
174        let cstr = str_from_c(s);
175        info!("{}", cstr);
176    }
177}
178
179// #define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id
180#[unsafe(no_mangle)]
181static mut __ESP_RADIO_WIFI_EVENT: esp_event_base_t = c"WIFI_EVENT".as_ptr();
182
183#[cfg(feature = "wifi")]
184pub unsafe extern "C" fn ets_timer_disarm(timer: *mut c_void) {
185    crate::compat::timer_compat::compat_timer_disarm(timer.cast());
186}
187
188#[cfg(feature = "wifi")]
189pub unsafe extern "C" fn ets_timer_done(timer: *mut c_void) {
190    crate::compat::timer_compat::compat_timer_done(timer.cast());
191}
192
193#[cfg(feature = "wifi")]
194pub unsafe extern "C" fn ets_timer_setfn(
195    ptimer: *mut c_void,
196    pfunction: *mut c_void,
197    parg: *mut c_void,
198) {
199    unsafe {
200        crate::compat::timer_compat::compat_timer_setfn(
201            ptimer.cast(),
202            core::mem::transmute::<*mut c_void, unsafe extern "C" fn(*mut c_void)>(pfunction),
203            parg,
204        );
205    }
206}
207
208#[cfg(feature = "wifi")]
209pub unsafe extern "C" fn ets_timer_arm(timer: *mut c_void, ms: u32, repeat: bool) {
210    crate::compat::timer_compat::compat_timer_arm(timer.cast(), ms, repeat);
211}
212
213#[cfg(feature = "wifi")]
214pub unsafe extern "C" fn ets_timer_arm_us(timer: *mut c_void, us: u32, repeat: bool) {
215    crate::compat::timer_compat::compat_timer_arm_us(timer.cast(), us, repeat);
216}
217
218#[unsafe(no_mangle)]
219pub unsafe extern "C" fn __esp_radio_gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 {
220    if !tv.is_null() {
221        unsafe {
222            let microseconds = __esp_radio_esp_timer_get_time();
223            (*tv).tv_sec = (microseconds / 1_000_000) as u64;
224            (*tv).tv_usec = (microseconds % 1_000_000) as u32;
225        }
226    }
227
228    0
229}
230
231/// **************************************************************************
232/// Name: esp_timer_get_time
233///
234/// Description:
235///   Get time in microseconds since boot.
236///
237/// Returned Value:
238///   System time in micros
239///
240/// *************************************************************************
241#[unsafe(no_mangle)]
242pub unsafe extern "C" fn __esp_radio_esp_timer_get_time() -> i64 {
243    trace!("esp_timer_get_time");
244    // Just using IEEE802.15.4 doesn't need the current time. If we don't use `preempt::now`, users
245    // will not need to have a scheduler in their firmware.
246    cfg_if::cfg_if! {
247        if #[cfg(any(feature = "wifi", feature = "ble"))] {
248            crate::preempt::now() as i64
249        } else {
250            // In this case we don't have a scheduler, we can return esp-hal's timestamp.
251            esp_hal::time::Instant::now().duration_since_epoch().as_micros() as i64
252        }
253    }
254}
255
256#[unsafe(no_mangle)]
257pub unsafe extern "C" fn __esp_radio_esp_fill_random(dst: *mut u8, len: u32) {
258    trace!("esp_fill_random");
259    unsafe {
260        let dst = core::slice::from_raw_parts_mut(dst, len as usize);
261
262        let rng = esp_hal::rng::Rng::new();
263        for chunk in dst.chunks_mut(4) {
264            let bytes = rng.random().to_le_bytes();
265            chunk.copy_from_slice(&bytes[..chunk.len()]);
266        }
267    }
268}
269
270#[unsafe(no_mangle)]
271pub unsafe extern "C" fn __esp_radio_strrchr(_s: *const (), _c: u32) -> *const u8 {
272    todo!("strrchr");
273}
274
275#[unsafe(no_mangle)]
276static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0;
277
278#[unsafe(no_mangle)]
279pub static mut __ESP_RADIO_G_MISC_NVS: *mut u32 = &raw mut NVS as *mut u32;
280
281pub static mut NVS: [u32; 15] = [0u32; 15];
282
283// For some reason these are only necessary on Xtensa chips.
284#[cfg(xtensa)]
285#[unsafe(no_mangle)]
286unsafe extern "C" fn __esp_radio_misc_nvs_deinit() {
287    trace!("misc_nvs_deinit")
288}
289
290#[cfg(xtensa)]
291#[unsafe(no_mangle)]
292unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 {
293    trace!("misc_nvs_init");
294    0
295}
296
297#[cfg(xtensa)]
298#[unsafe(no_mangle)]
299unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 {
300    todo!("misc_nvs_restore")
301}
302
303// Clock control is no-op because the wifi blobs don't symmetrically enable/disable the clock,
304// causing an eventual overflow. Currently we are holding onto a guard ourselves while Wi-Fi/BT is
305// active, so the blobs should not be able to disable the clock anyway.
306//
307// This might have some low-power issues, but we're not there yet anyway.
308#[allow(unused)]
309pub(crate) unsafe fn phy_enable_clock() {
310    // Stealing the peripheral is safe here, as they must have been passed into the relevant
311    // initialization functions for the Wi-Fi or BLE controller, if this code gets executed.
312}
313
314#[allow(unused)]
315pub(crate) unsafe fn phy_disable_clock() {
316    // No-op, see `phy_enable_clock`.
317}
318
319pub(crate) fn enable_wifi_power_domain() {
320    #[cfg(not(any(soc_has_pmu, esp32c2)))]
321    {
322        // C5, C6 have `LP_CLKRST`, but they're cfg'd out with `not(soc_has_pmu)`
323        // TODO: revisit this code (https://github.com/esp-rs/esp-hal/pull/5066#discussion_r2858978902)
324        let rtc_cntl = regs!(RTC_CNTL);
325
326        rtc_cntl
327            .dig_pwc()
328            .modify(|_, w| w.wifi_force_pd().clear_bit());
329
330        #[cfg(not(esp32))]
331        cfg_if::cfg_if! {
332            if #[cfg(soc_has_apb_ctrl)] {
333                let syscon = regs!(APB_CTRL);
334            } else { // S2
335                let syscon = regs!(SYSCON);
336            }
337        }
338        #[cfg(not(esp32))]
339        unsafe {
340            const WIFIBB_RST: u32 = 1 << 0; // Wi-Fi baseband
341            const FE_RST: u32 = 1 << 1; // RF Frontend RST
342            const WIFIMAC_RST: u32 = 1 << 2; // Wi-Fi MAC
343
344            const BTBB_RST: u32 = 1 << 3; // Bluetooth Baseband
345            const BTMAC_RST: u32 = 1 << 4; // deprecated
346            const RW_BTMAC_RST: u32 = 1 << 9; // Bluetooth MAC
347            const RW_BTMAC_REG_RST: u32 = 1 << 11; // Bluetooth MAC Regsiters
348            const BTBB_REG_RST: u32 = 1 << 13; // Bluetooth Baseband Registers
349
350            const MODEM_RESET_FIELD_WHEN_PU: u32 = WIFIBB_RST
351                | FE_RST
352                | WIFIMAC_RST
353                | if cfg!(soc_has_bt) {
354                    BTBB_RST | BTMAC_RST | RW_BTMAC_RST | RW_BTMAC_REG_RST | BTBB_RST
355                } else {
356                    0
357                };
358
359            syscon
360                .wifi_rst_en()
361                .modify(|r, w| w.bits(r.bits() | MODEM_RESET_FIELD_WHEN_PU));
362            syscon
363                .wifi_rst_en()
364                .modify(|r, w| w.bits(r.bits() & !MODEM_RESET_FIELD_WHEN_PU));
365        }
366
367        rtc_cntl
368            .dig_iso()
369            .modify(|_, w| w.wifi_force_iso().clear_bit());
370    }
371}
372
373/// **************************************************************************
374/// Name: esp_queue_create
375///
376/// Description:
377///   Create message queue
378///
379/// Input Parameters:
380///   queue_len - queue message number
381///   item_size - message size
382///
383/// Returned Value:
384///   Message queue data pointer
385///
386/// *************************************************************************
387pub unsafe extern "C" fn queue_create(queue_len: u32, item_size: u32) -> *mut c_void {
388    crate::compat::queue::queue_create(queue_len as i32, item_size as i32).cast()
389}
390
391/// **************************************************************************
392/// Name: esp_queue_delete
393///
394/// Description:
395///   Delete message queue
396///
397/// Input Parameters:
398///   queue - Message queue data pointer
399///
400/// Returned Value:
401///   None
402///
403/// *************************************************************************
404pub unsafe extern "C" fn queue_delete(queue: *mut c_void) {
405    crate::compat::queue::queue_delete(queue.cast());
406}
407
408/// **************************************************************************
409/// Name: esp_queue_send
410///
411/// Description:
412///   Send message of low priority to queue within a certain period of time
413///
414/// Input Parameters:
415///   queue - Message queue data pointer
416///   item  - Message data pointer
417///   ticks - Wait ticks
418///
419/// Returned Value:
420///   True if success or false if fail
421///
422/// *************************************************************************
423pub unsafe extern "C" fn queue_send(
424    queue: *mut c_void,
425    item: *mut c_void,
426    block_time_tick: u32,
427) -> i32 {
428    crate::compat::queue::queue_send_to_back(
429        queue.cast(),
430        item.cast_const(),
431        blob_ticks_to_micros(block_time_tick),
432    )
433}
434
435/// **************************************************************************
436/// Name: esp_queue_send_from_isr
437///
438/// Description:
439///   Send message of low priority to queue in ISR within
440///   a certain period of time
441///
442/// Input Parameters:
443///   queue - Message queue data pointer
444///   item  - Message data pointer
445///   hptw  - No mean
446///
447/// Returned Value:
448///   True if success or false if fail
449///
450/// *************************************************************************
451pub unsafe extern "C" fn queue_send_from_isr(
452    queue: *mut c_void,
453    item: *mut c_void,
454    higher_priority_task_waken: *mut c_void,
455) -> i32 {
456    crate::compat::queue::queue_try_send_to_back_from_isr(
457        queue.cast(),
458        item.cast_const(),
459        higher_priority_task_waken.cast(),
460    )
461}
462
463/// **************************************************************************
464/// Name: esp_queue_send_to_back
465///
466/// Description:
467///   Send message of low priority to queue within a certain period of time
468///
469/// Input Parameters:
470///   queue - Message queue data pointer
471///   item  - Message data pointer
472///   ticks - Wait ticks
473///
474/// Returned Value:
475///   True if success or false if fail
476///
477/// *************************************************************************
478pub unsafe extern "C" fn queue_send_to_back(
479    queue: *mut c_void,
480    item: *mut c_void,
481    block_time_tick: u32,
482) -> i32 {
483    crate::compat::queue::queue_send_to_back(
484        queue.cast(),
485        item,
486        blob_ticks_to_micros(block_time_tick),
487    )
488}
489
490/// **************************************************************************
491/// Name: esp_queue_send_from_to_front
492///
493/// Description:
494///   Send message of high priority to queue within a certain period of time
495///
496/// Input Parameters:
497///   queue - Message queue data pointer
498///   item  - Message data pointer
499///   ticks - Wait ticks
500///
501/// Returned Value:
502///   True if success or false if fail
503///
504/// *************************************************************************
505pub unsafe extern "C" fn queue_send_to_front(
506    queue: *mut c_void,
507    item: *mut c_void,
508    block_time_tick: u32,
509) -> i32 {
510    crate::compat::queue::queue_send_to_front(
511        queue.cast(),
512        item,
513        blob_ticks_to_micros(block_time_tick),
514    )
515}
516
517/// **************************************************************************
518/// Name: esp_queue_recv
519///
520/// Description:
521///   Receive message from queue within a certain period of time
522///
523/// Input Parameters:
524///   queue - Message queue data pointer
525///   item  - Message data pointer
526///   ticks - Wait ticks
527///
528/// Returned Value:
529///   True if success or false if fail
530///
531/// *************************************************************************
532pub unsafe extern "C" fn queue_recv(
533    queue: *mut c_void,
534    item: *mut c_void,
535    block_time_ms: u32,
536) -> i32 {
537    crate::compat::queue::queue_receive(queue.cast(), item, blob_ticks_to_micros(block_time_ms))
538}
539
540pub unsafe extern "C" fn queue_recv_from_isr(
541    queue: *mut c_void,
542    item: *mut c_void,
543    higher_priority_task_waken: *mut c_void,
544) -> i32 {
545    crate::compat::queue::queue_try_receive_from_isr(
546        queue.cast(),
547        item,
548        higher_priority_task_waken.cast(),
549    )
550}
551
552/// **************************************************************************
553/// Name: esp_queue_msg_waiting
554///
555/// Description:
556///   Get message number in the message queue
557///
558/// Input Parameters:
559///   queue - Message queue data pointer
560///
561/// Returned Value:
562///   Message number
563///
564/// *************************************************************************
565pub unsafe extern "C" fn queue_msg_waiting(queue: *mut c_void) -> u32 {
566    crate::compat::queue::queue_messages_waiting(queue.cast())
567}
568
569#[allow(unused)]
570#[unsafe(no_mangle)]
571pub unsafe extern "C" fn __esp_radio_esp_event_post(
572    event_base: *const c_char,
573    event_id: i32,
574    event_data: *mut c_void,
575    event_data_size: usize,
576    ticks_to_wait: u32,
577) -> i32 {
578    #[cfg(feature = "wifi")]
579    return unsafe {
580        crate::wifi::event_post(
581            event_base,
582            event_id,
583            event_data,
584            event_data_size,
585            ticks_to_wait,
586        )
587    };
588
589    #[cfg(not(feature = "wifi"))]
590    return -1;
591}
592
593#[unsafe(no_mangle)]
594pub unsafe extern "C" fn __esp_radio_vTaskDelay(ticks: u32) {
595    unsafe {
596        crate::compat::common::__esp_radio_usleep(crate::time::blob_ticks_to_micros(ticks));
597    }
598}