esp_radio/
common_adapter.rs

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