esp_wifi/common_adapter/
mod.rs

1use esp_wifi_sys::{
2    c_types::c_char,
3    include::{
4        esp_phy_calibration_data_t,
5        esp_phy_calibration_mode_t,
6        get_phy_version_str,
7        register_chipv7_phy,
8        timeval,
9    },
10};
11use portable_atomic::{AtomicU32, Ordering};
12
13use crate::{
14    binary::include::{esp_event_base_t, esp_timer_get_time},
15    compat::{common::*, timer_compat::*},
16    hal::{self, clock::RadioClockController, peripherals::RADIO_CLK, ram},
17};
18
19#[cfg_attr(esp32c3, path = "common_adapter_esp32c3.rs")]
20#[cfg_attr(esp32c2, path = "common_adapter_esp32c2.rs")]
21#[cfg_attr(esp32c6, path = "common_adapter_esp32c6.rs")]
22#[cfg_attr(esp32h2, path = "common_adapter_esp32h2.rs")]
23#[cfg_attr(esp32, path = "common_adapter_esp32.rs")]
24#[cfg_attr(esp32s3, path = "common_adapter_esp32s3.rs")]
25#[cfg_attr(esp32s2, path = "common_adapter_esp32s2.rs")]
26pub(crate) mod chip_specific;
27
28#[cfg_attr(esp32c3, path = "phy_init_data_esp32c3.rs")]
29#[cfg_attr(esp32c2, path = "phy_init_data_esp32c2.rs")]
30#[cfg_attr(esp32c6, path = "phy_init_data_esp32c6.rs")]
31#[cfg_attr(esp32h2, path = "phy_init_data_esp32h2.rs")]
32#[cfg_attr(esp32, path = "phy_init_data_esp32.rs")]
33#[cfg_attr(esp32s3, path = "phy_init_data_esp32s3.rs")]
34#[cfg_attr(esp32s2, path = "phy_init_data_esp32s2.rs")]
35pub(crate) mod phy_init_data;
36
37/// **************************************************************************
38/// Name: esp_semphr_create
39///
40/// Description:
41///   Create and initialize semaphore
42///
43/// Input Parameters:
44///   max  - No mean
45///   init - semaphore initialization value
46///
47/// Returned Value:
48///   Semaphore data pointer
49///
50/// *************************************************************************
51#[allow(unused)]
52pub unsafe extern "C" fn semphr_create(max: u32, init: u32) -> *mut crate::binary::c_types::c_void {
53    trace!("semphr_create - max {} init {}", max, init);
54    sem_create(max, init)
55}
56
57/// **************************************************************************
58/// Name: esp_semphr_delete
59///
60/// Description:
61///   Delete semaphore
62///
63/// Input Parameters:
64///   semphr - Semaphore data pointer
65///
66/// Returned Value:
67///   None
68///
69/// *************************************************************************
70#[allow(unused)]
71pub unsafe extern "C" fn semphr_delete(semphr: *mut crate::binary::c_types::c_void) {
72    trace!("semphr_delete {:?}", semphr);
73    sem_delete(semphr);
74}
75
76/// **************************************************************************
77/// Name: esp_semphr_take
78///
79/// Description:
80///   Wait semaphore within a certain period of time
81///
82/// Input Parameters:
83///   semphr - Semaphore data pointer
84///   ticks  - Wait system ticks
85///
86/// Returned Value:
87///   True if success or false if fail
88///
89/// *************************************************************************
90#[ram]
91pub unsafe extern "C" fn semphr_take(
92    semphr: *mut crate::binary::c_types::c_void,
93    tick: u32,
94) -> i32 {
95    sem_take(semphr, tick)
96}
97
98/// **************************************************************************
99/// Name: esp_semphr_give
100///
101/// Description:
102///   Post semaphore
103///
104/// Input Parameters:
105///   semphr - Semaphore data pointer
106///
107/// Returned Value:
108///   True if success or false if fail
109///
110/// *************************************************************************
111#[ram]
112pub unsafe extern "C" fn semphr_give(semphr: *mut crate::binary::c_types::c_void) -> i32 {
113    sem_give(semphr)
114}
115
116/// **************************************************************************
117/// Name: esp_random_ulong
118/// *************************************************************************
119#[allow(unused)]
120#[ram]
121#[unsafe(no_mangle)]
122pub unsafe extern "C" fn random() -> crate::binary::c_types::c_ulong {
123    trace!("random");
124
125    // stealing RNG is safe since we own it (passed into `init`)
126    let mut rng = hal::rng::Rng::new(unsafe { hal::peripherals::RNG::steal() });
127    rng.random()
128}
129
130/// **************************************************************************
131/// Name: esp_wifi_read_mac
132///
133/// Description:
134///   Read MAC address from efuse
135///
136/// Input Parameters:
137///   mac  - MAC address buffer pointer
138///   type - MAC address type
139///
140/// Returned Value:
141///   0 if success or -1 if fail
142///
143/// *************************************************************************
144pub unsafe extern "C" fn read_mac(mac: *mut u8, type_: u32) -> crate::binary::c_types::c_int {
145    trace!("read_mac {:?} {}", mac, type_);
146
147    let base_mac = hal::efuse::Efuse::mac_address();
148
149    for (i, &byte) in base_mac.iter().enumerate() {
150        unsafe {
151            mac.add(i).write_volatile(byte);
152        }
153    }
154
155    unsafe {
156        // ESP_MAC_WIFI_SOFTAP
157        if type_ == 1 {
158            let tmp = mac.offset(0).read_volatile();
159            for i in 0..64 {
160                mac.offset(0).write_volatile(tmp | 0x02);
161                mac.offset(0)
162                    .write_volatile(mac.offset(0).read_volatile() ^ (i << 2));
163
164                if mac.offset(0).read_volatile() != tmp {
165                    break;
166                }
167            }
168        }
169
170        // ESP_MAC_BT
171        if type_ == 2 {
172            let tmp = mac.offset(0).read_volatile();
173            for i in 0..64 {
174                mac.offset(0).write_volatile(tmp | 0x02);
175                mac.offset(0)
176                    .write_volatile(mac.offset(0).read_volatile() ^ (i << 2));
177
178                if mac.offset(0).read_volatile() != tmp {
179                    break;
180                }
181            }
182
183            mac.offset(5)
184                .write_volatile(mac.offset(5).read_volatile() + 1);
185        }
186    }
187
188    0
189}
190
191#[allow(unused)]
192#[ram]
193pub(crate) unsafe extern "C" fn semphr_take_from_isr(sem: *const (), hptw: *const ()) -> i32 {
194    trace!("sem take from isr");
195    unsafe {
196        (hptw as *mut u32).write_volatile(0);
197        crate::common_adapter::semphr_take(sem as *mut crate::binary::c_types::c_void, 0)
198    }
199}
200
201#[allow(unused)]
202#[ram]
203pub(crate) unsafe extern "C" fn semphr_give_from_isr(sem: *const (), hptw: *const ()) -> i32 {
204    trace!("sem give from isr");
205    unsafe {
206        (hptw as *mut u32).write_volatile(0);
207        crate::common_adapter::semphr_give(sem as *mut crate::binary::c_types::c_void)
208    }
209}
210
211// other functions
212#[unsafe(no_mangle)]
213pub unsafe extern "C" fn puts(s: *const c_char) {
214    unsafe {
215        let cstr = str_from_c(s);
216        info!("{}", cstr);
217    }
218}
219
220// #define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id
221#[unsafe(no_mangle)]
222static mut WIFI_EVENT: esp_event_base_t = c"WIFI_EVENT".as_ptr();
223
224// stuff needed by wpa-supplicant
225#[unsafe(no_mangle)]
226pub unsafe extern "C" fn __assert_func(
227    file: *const c_char,
228    line: u32,
229    func: *const c_char,
230    failed_expr: *const c_char,
231) {
232    unsafe {
233        let file = str_from_c(file);
234        let (func_pre, func) = if func.is_null() {
235            ("", "")
236        } else {
237            (", function: ", str_from_c(func))
238        };
239        let expr = str_from_c(failed_expr);
240
241        panic!(
242            "assertion \"{}\" failed: file \"{}\", line {}{}{}",
243            expr, file, line, func_pre, func
244        );
245    }
246}
247
248#[unsafe(no_mangle)]
249pub unsafe extern "C" fn ets_timer_disarm(timer: *mut crate::binary::c_types::c_void) {
250    compat_timer_disarm(timer.cast());
251}
252
253#[unsafe(no_mangle)]
254pub unsafe extern "C" fn ets_timer_done(timer: *mut crate::binary::c_types::c_void) {
255    compat_timer_done(timer.cast());
256}
257
258#[unsafe(no_mangle)]
259pub unsafe extern "C" fn ets_timer_setfn(
260    ptimer: *mut crate::binary::c_types::c_void,
261    pfunction: *mut crate::binary::c_types::c_void,
262    parg: *mut crate::binary::c_types::c_void,
263) {
264    unsafe {
265        compat_timer_setfn(
266            ptimer.cast(),
267            core::mem::transmute::<
268                *mut crate::binary::c_types::c_void,
269                unsafe extern "C" fn(*mut crate::binary::c_types::c_void),
270            >(pfunction),
271            parg,
272        );
273    }
274}
275
276#[unsafe(no_mangle)]
277pub unsafe extern "C" fn ets_timer_arm(
278    timer: *mut crate::binary::c_types::c_void,
279    tmout: u32,
280    repeat: bool,
281) {
282    compat_timer_arm(timer.cast(), tmout, repeat);
283}
284
285#[unsafe(no_mangle)]
286pub unsafe extern "C" fn ets_timer_arm_us(
287    timer: *mut crate::binary::c_types::c_void,
288    tmout: u32,
289    repeat: bool,
290) {
291    compat_timer_arm_us(timer.cast(), tmout, repeat);
292}
293
294#[unsafe(no_mangle)]
295pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 {
296    if !tv.is_null() {
297        unsafe {
298            let microseconds = esp_timer_get_time();
299            (*tv).tv_sec = (microseconds / 1_000_000) as u64;
300            (*tv).tv_usec = (microseconds % 1_000_000) as u32;
301        }
302    }
303
304    0
305}
306
307#[unsafe(no_mangle)]
308pub unsafe extern "C" fn esp_fill_random(dst: *mut u8, len: u32) {
309    trace!("esp_fill_random");
310    unsafe {
311        let dst = core::slice::from_raw_parts_mut(dst, len as usize);
312
313        // stealing RNG is safe since we own it (passed into `init`)
314        let mut rng = esp_hal::rng::Rng::new(esp_hal::peripherals::RNG::steal());
315        for chunk in dst.chunks_mut(4) {
316            let bytes = rng.random().to_le_bytes();
317            chunk.copy_from_slice(&bytes[..chunk.len()]);
318        }
319    }
320}
321
322#[unsafe(no_mangle)]
323pub unsafe extern "C" fn strrchr(_s: *const (), _c: u32) -> *const u8 {
324    todo!("strrchr");
325}
326
327static PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0);
328
329pub(crate) unsafe fn phy_enable_clock() {
330    let count = PHY_CLOCK_ENABLE_REF.fetch_add(1, Ordering::Acquire);
331    if count == 0 {
332        // stealing RADIO_CLK is safe since it is passed (as mutable reference or by
333        // value) into `init`
334        let radio_clocks = unsafe { RADIO_CLK::steal() };
335        RadioClockController::new(radio_clocks).enable_phy(true);
336        trace!("phy_enable_clock done!");
337    }
338}
339
340#[allow(unused)]
341pub(crate) unsafe fn phy_disable_clock() {
342    let count = PHY_CLOCK_ENABLE_REF.fetch_sub(1, Ordering::Release);
343    if count == 1 {
344        // stealing RADIO_CLK is safe since it is passed (as mutable reference or by
345        // value) into `init`
346        let radio_clocks = unsafe { RADIO_CLK::steal() };
347        RadioClockController::new(radio_clocks).enable_phy(false);
348        trace!("phy_disable_clock done!");
349    }
350}
351
352pub(crate) fn phy_calibrate() {
353    let mut cal_data: [u8; core::mem::size_of::<esp_phy_calibration_data_t>()] =
354        [0u8; core::mem::size_of::<esp_phy_calibration_data_t>()];
355
356    let phy_version = unsafe { get_phy_version_str() };
357    trace!("phy_version {}", unsafe { str_from_c(phy_version) });
358
359    let init_data = &phy_init_data::PHY_INIT_DATA_DEFAULT;
360
361    unsafe {
362        chip_specific::bbpll_en_usb();
363
364        cfg_if::cfg_if! {
365            if #[cfg(phy_full_calibration)] {
366                const CALIBRATION_MODE: esp_phy_calibration_mode_t = esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_FULL;
367            } else {
368                const CALIBRATION_MODE: esp_phy_calibration_mode_t = esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_PARTIAL;
369            }
370        };
371
372        cfg_if::cfg_if! {
373            if #[cfg(phy_skip_calibration_after_deep_sleep)] {
374                let calibration_mode = if crate::hal::system::reset_reason() == Some(crate::hal::rtc_cntl::SocResetReason::CoreDeepSleep) {
375                    esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_NONE
376                } else {
377                    CALIBRATION_MODE
378                };
379            } else {
380                let calibration_mode = CALIBRATION_MODE;
381            }
382        };
383
384        debug!("Using calibration mode {}", calibration_mode);
385
386        register_chipv7_phy(
387            init_data,
388            &mut cal_data as *mut _ as *mut crate::binary::include::esp_phy_calibration_data_t,
389            calibration_mode,
390        );
391    }
392}