From f71cb419eff43d493bae047cb2f1067222e98a50 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 16 Sep 2022 09:49:20 +0200 Subject: [PATCH] Add support for ESP32-S2 wifi --- .cargo/config.toml | 18 ++ Cargo.toml | 16 +- README.md | 3 +- build.rs | 80 ++++++- examples/dhcp.rs | 10 +- ld/esp32s2/rom_functions.x | 69 ++++++ src/binary/include_esp32s2.rs | 7 +- src/binary/mod.rs | 1 + src/common_adapter/common_adapter_esp32s2.rs | 218 +++++++++++++++++++ src/common_adapter/mod.rs | 13 +- src/common_adapter/phy_init_data_esp32s2.rs | 146 +++++++++++++ src/compat/common.rs | 7 +- src/lib.rs | 5 +- src/timer_esp32s2.rs | 101 +++++++++ src/wifi/mod.rs | 8 +- src/wifi/os_adapter.rs | 3 +- src/wifi/os_adapter_esp32s2.rs | 55 +++++ 17 files changed, 733 insertions(+), 27 deletions(-) create mode 100644 ld/esp32s2/rom_functions.x create mode 100644 src/common_adapter/common_adapter_esp32s2.rs create mode 100644 src/common_adapter/phy_init_data_esp32s2.rs create mode 100644 src/timer_esp32s2.rs create mode 100644 src/wifi/os_adapter_esp32s2.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 05c5db35..22261d51 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -24,6 +24,24 @@ rustflags = [ "-C", "link-arg=-Tesp32s3_rom_functions.x", ] +[target.xtensa-esp32s2-none-elf] +runner = "espflash --speed 921600 --monitor" + +rustflags = [ + "-C", "link-arg=-Tlinkall.x", + "-C", "link-arg=-Tesp32s2_rom_functions.x", + + # Enable the atomic codegen option for Xtensa + "-C", "target-feature=+s32c1i", + + # Tell the `core` library that we have atomics, even though it's not + # specified in the target definition + "--cfg", 'target_has_atomic="8"', + "--cfg", 'target_has_atomic="16"', + "--cfg", 'target_has_atomic="32"', + "--cfg", 'target_has_atomic="ptr"', +] + [build] target = "riscv32imc-unknown-none-elf" diff --git a/Cargo.toml b/Cargo.toml index a24af65e..5abb4aa3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ void = { version = "1.0.2", default-features = false } esp32c3-hal = { version = "0.2.0", optional = true } esp32-hal = { version = "0.5.0", optional = true, features = [ "bluetooth","rt" ] } esp32s3-hal = { version = "0.2.0", optional = true, features = [ "rt" ] } +esp32s2-hal = { version = "0.2.0", optional = true, features = [ "rt" ] } riscv-rt = { version = "0.9.0", optional = true } riscv = { version = "0.8.0", optional = true } xtensa-lx-rt = { version = "0.13.0", optional = true } @@ -36,22 +37,28 @@ riscv-target = { version = "0.1.2", optional = true } ble-hci = { git = "https://github.com/bjoernQ/ble-hci", branch = "embedded-io" } [target.xtensa-esp32-none-elf.dev-dependencies] -esp-println = { version = "0.3.0", features = [ "esp32", "log" ] } +esp-println = { version = "0.3.1", features = [ "esp32", "log" ] } esp-backtrace = { version = "0.2.0", features = [ "esp32", "panic-handler", "exception-handler", "print-uart" ] } [target.riscv32imc-unknown-none-elf.dev-dependencies] -esp-println = { version = "0.3.0", features = [ "esp32c3", "log" ] } +esp-println = { version = "0.3.1", features = [ "esp32c3", "log" ] } esp-backtrace = { version = "0.2.0" , features = [ "esp32c3", "panic-handler", "exception-handler", "print-uart" ] } [target.xtensa-esp32s3-none-elf.dev-dependencies] -esp-println = { version = "0.3.0", features = [ "esp32s3", "log" ] } +esp-println = { version = "0.3.1", features = [ "esp32s3", "log" ] } esp-backtrace = { version = "0.2.0", features = [ "esp32s3", "panic-handler", "exception-handler", "print-uart" ] } +[target.xtensa-esp32s2-none-elf.dev-dependencies] +esp-println = { version = "0.3.1", features = [ "esp32s2", "log", "critical-section" ] } +esp-backtrace = { version = "0.2.0", features = [ "esp32s2", "panic-handler", "exception-handler", "print-uart" ] } +xtensa-atomic-emulation-trap = "0.2.0" + [features] default = [ "utils" ] esp32c3 = [ "riscv-target", "riscv", "riscv-rt", "esp32c3-hal" ] esp32 = [ "esp32-hal", "xtensa-lx-rt/esp32", "xtensa-lx/esp32" ] esp32s3 = [ "esp32s3-hal", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3" ] +esp32s2 = [ "esp32s2-hal", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2" ] wifi_logs = [] dump_packets = [] utils = [] @@ -62,4 +69,5 @@ ble = [] # currently published versions don't contain all relevant adjustments - using git dependencies for now [patch.crates-io] -esp32s3-hal = { git = "https://github.com/esp-rs/esp-hal/", package = "esp32s3-hal", rev = "6eea2f266a451678d244917329e2e885940fce9c" } +esp32s3-hal = { git = "https://github.com/esp-rs/esp-hal/", package = "esp32s3-hal", rev = "b1d5e37f36508ccfa835b236b2d30c3115bd3f72" } +esp32s2-hal = { git = "https://github.com/esp-rs/esp-hal/", package = "esp32s2-hal", rev = "b1d5e37f36508ccfa835b236b2d30c3115bd3f72" } diff --git a/README.md b/README.md index ffdb2862..d5442d42 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wifi and Bluetooth LE on ESP32-C3,ESP32 and ESP32-S3 (on bare-metal Rust) +# Wifi and Bluetooth LE on ESP32-C3,ESP32,ESP32-S3 and ESP32-S2 (on bare-metal Rust) ## About @@ -46,6 +46,7 @@ https://github.com/esp-rs/esp-wireless-drivers-3rdparty/ (commit 8e5147d2de8d9b9 | `cargo "+esp" run --example ble --release --target xtensa-esp32-none-elf --features "esp32,ble"` | ESP32 | | `cargo "+esp" run --example dhcp --release --target xtensa-esp32-none-elf --features "esp32,embedded-svc,wifi"` | ESP32 | | `cargo "+esp" run --example dhcp --release --target xtensa-esp32s3-none-elf --features "esp32s3,embedded-svc,wifi"` | ESP32-S3| +| `cargo "+esp" run --example dhcp --release --target xtensa-esp32s2-none-elf --features "esp32s2,embedded-svc,wifi"` | ESP32-S2| Additional you can specify these features |Feature|Meaning| diff --git a/build.rs b/build.rs index baf24769..19f16b3c 100644 --- a/build.rs +++ b/build.rs @@ -3,7 +3,12 @@ use std::fs::File; use std::io::Write; use std::path::PathBuf; -#[cfg(any(feature = "esp32c3", feature = "esp32", feature = "esp32s3"))] +#[cfg(any( + feature = "esp32c3", + feature = "esp32", + feature = "esp32s3", + feature = "esp32s2" +))] fn main() -> Result<(), String> { let features: u8 = cfg!(feature = "wifi") as u8 + cfg!(feature = "ble") as u8; @@ -15,6 +20,10 @@ fn main() -> Result<(), String> { return Err("BLE is not yet supported for ESP32-S3".into()); } + if cfg!(feature = "esp32s2") && cfg!(feature = "ble") { + return Err("BLE is not supported for ESP32-S2".into()); + } + if features >= 2 { println!("cargo:rustc-cfg=coex"); } @@ -191,7 +200,6 @@ fn handle_chip() { ); copy(out, include_bytes!("libs/esp32s3/libphy.a"), "libphy.a"); copy(out, include_bytes!("libs/esp32s3/libpp.a"), "libpp.a"); - //copy(out, include_bytes!("libs/esp32s3/librtc.a"), "librtc.a"); copy( out, include_bytes!("libs/esp32s3/libsmartconfig.a"), @@ -212,7 +220,66 @@ fn handle_chip() { println!("cargo:rustc-link-lib={}", "net80211"); println!("cargo:rustc-link-lib={}", "phy"); println!("cargo:rustc-link-lib={}", "pp"); - //println!("cargo:rustc-link-lib={}", "rtc"); + println!("cargo:rustc-link-lib={}", "smartconfig"); + println!("cargo:rustc-link-lib={}", "wapi"); + println!("cargo:rustc-link-lib={}", "wpa_supplicant"); + + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=memory.x"); +} + +#[cfg(feature = "esp32s2")] +fn handle_chip() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + copy( + out, + include_bytes!("ld/esp32s2/rom_functions.x"), + "esp32s2_rom_functions.x", + ); + + copy( + out, + include_bytes!("libs/esp32s2/libcoexist.a"), + "libcoexist.a", + ); + copy(out, include_bytes!("libs/esp32s2/libcore.a"), "libcore.a"); + copy( + out, + include_bytes!("libs/esp32s2/libespnow.a"), + "libespnow.a", + ); + copy(out, include_bytes!("libs/esp32s2/libmesh.a"), "libmesh.a"); + copy( + out, + include_bytes!("libs/esp32s2/libnet80211.a"), + "libnet80211.a", + ); + copy(out, include_bytes!("libs/esp32s2/libphy.a"), "libphy.a"); + copy(out, include_bytes!("libs/esp32s2/libpp.a"), "libpp.a"); + copy( + out, + include_bytes!("libs/esp32s2/libsmartconfig.a"), + "libsmartconfig.a", + ); + copy(out, include_bytes!("libs/esp32s2/libwapi.a"), "libwapi.a"); + copy( + out, + include_bytes!("libs/esp32s2/libwpa_supplicant.a"), + "libwpa_supplicant.a", + ); + + println!("cargo:rustc-link-lib={}", "coexist"); + println!("cargo:rustc-link-lib={}", "core"); + println!("cargo:rustc-link-lib={}", "espnow"); + println!("cargo:rustc-link-lib={}", "mesh"); + println!("cargo:rustc-link-lib={}", "net80211"); + println!("cargo:rustc-link-lib={}", "phy"); + println!("cargo:rustc-link-lib={}", "pp"); println!("cargo:rustc-link-lib={}", "smartconfig"); println!("cargo:rustc-link-lib={}", "wapi"); println!("cargo:rustc-link-lib={}", "wpa_supplicant"); @@ -231,7 +298,12 @@ fn copy(path: &PathBuf, data: &[u8], name: &str) { .unwrap(); } -#[cfg(not(any(feature = "esp32c3", feature = "esp32", feature = "esp32s3")))] +#[cfg(not(any( + feature = "esp32c3", + feature = "esp32", + feature = "esp32s3", + feature = "esp32s2" +)))] fn main() { panic!("Select a chip via it's cargo feature"); } diff --git a/examples/dhcp.rs b/examples/dhcp.rs index 6fcc6537..fee824f2 100644 --- a/examples/dhcp.rs +++ b/examples/dhcp.rs @@ -7,6 +7,8 @@ use esp32_hal as hal; #[cfg(feature = "esp32c3")] use esp32c3_hal as hal; +#[cfg(feature = "esp32s2")] +use esp32s2_hal as hal; #[cfg(feature = "esp32s3")] use esp32s3_hal as hal; @@ -32,7 +34,7 @@ use hal::system::SystemExt; #[cfg(feature = "esp32c3")] use riscv_rt::entry; -#[cfg(any(feature = "esp32", feature = "esp32s3"))] +#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] use xtensa_lx_rt::entry; extern crate alloc; @@ -54,13 +56,13 @@ fn main() -> ! { #[cfg(feature = "esp32c3")] let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze(); - #[cfg(any(feature = "esp32", feature = "esp32s3"))] + #[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock240MHz).freeze(); let mut rtc = Rtc::new(peripherals.RTC_CNTL); // Disable watchdog timers - #[cfg(not(feature = "esp32"))] + #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] rtc.swd.disable(); rtc.rwdt.disable(); @@ -75,7 +77,7 @@ fn main() -> ! { let syst = SystemTimer::new(peripherals.SYSTIMER); initialize(syst.alarm0, peripherals.RNG, &clocks).unwrap(); } - #[cfg(any(feature = "esp32", feature = "esp32s3"))] + #[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] { use hal::timer::TimerGroup; let timg1 = TimerGroup::new(peripherals.TIMG1, &clocks); diff --git a/ld/esp32s2/rom_functions.x b/ld/esp32s2/rom_functions.x new file mode 100644 index 00000000..87f22b11 --- /dev/null +++ b/ld/esp32s2/rom_functions.x @@ -0,0 +1,69 @@ +/** + * ROM APIs + */ + +PROVIDE ( esp_rom_crc32_le = crc32_le ); +PROVIDE ( esp_rom_crc16_le = crc16_le ); +PROVIDE ( esp_rom_crc8_le = crc8_le ); + +PROVIDE ( esp_rom_gpio_pad_select_gpio = gpio_pad_select_gpio ); +PROVIDE ( esp_rom_gpio_pad_pullup_only = gpio_pad_pullup ); +PROVIDE ( esp_rom_gpio_pad_set_drv = gpio_pad_set_drv ); +PROVIDE ( esp_rom_gpio_pad_unhold = gpio_pad_unhold ); +PROVIDE ( esp_rom_gpio_connect_in_signal = gpio_matrix_in ); +PROVIDE ( esp_rom_gpio_connect_out_signal = gpio_matrix_out ); + +PROVIDE ( esp_rom_efuse_mac_address_crc8 = esp_crc8 ); +PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig ); +PROVIDE ( esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad ); +PROVIDE ( esp_rom_efuse_get_opiconfig = ets_efuse_get_opiconfig ); +PROVIDE ( esp_rom_efuse_is_secure_boot_enabled = ets_efuse_secure_boot_enabled ); + +PROVIDE ( esp_rom_uart_flush_tx = uart_tx_flush ); +PROVIDE ( esp_rom_uart_tx_one_char = uart_tx_one_char ); +PROVIDE ( esp_rom_uart_tx_wait_idle = uart_tx_wait_idle ); +PROVIDE ( esp_rom_uart_rx_one_char = uart_rx_one_char ); +PROVIDE ( esp_rom_uart_rx_string = UartRxString ); +PROVIDE ( esp_rom_uart_set_as_console = uart_tx_switch ); +PROVIDE ( esp_rom_uart_usb_acm_init = Uart_Init_USB ); +PROVIDE ( esp_rom_uart_putc = ets_write_char_uart ); + +/* wpa_supplicant re-implements the MD5 functions: MD5Init, MD5Update, MD5Final */ +/* so here we directly assign the symbols with the ROM API address */ +PROVIDE ( esp_rom_md5_init = 0x4000526c ); +PROVIDE ( esp_rom_md5_update = 0x4000528c ); +PROVIDE ( esp_rom_md5_final = 0x4000530c ); + +PROVIDE ( esp_rom_printf = ets_printf ); +PROVIDE ( esp_rom_delay_us = ets_delay_us ); +PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf ); +PROVIDE ( esp_rom_get_reset_reason = rtc_get_reset_reason ); +PROVIDE ( esp_rom_route_intr_matrix = intr_matrix_set ); +PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency ); + +PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock ); +PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable); + +PROVIDE ( esp_rom_spiflash_fix_dummylen = spi_dummy_len_fix ); +PROVIDE ( esp_rom_spiflash_set_drvs = SetSpiDrvs); +PROVIDE ( esp_rom_spiflash_select_padsfunc = SelectSpiFunction ); +PROVIDE ( esp_rom_spiflash_common_cmd = SPI_Common_Command ); + +/* from esp32s2.rom.ld */ +PROVIDE ( ets_delay_us = 0x4000d888 ); +PROVIDE ( roundup2 = 0x4001bcd0 ); +PROVIDE ( g_phyFuns = 0x3ffffd90 ); +PROVIDE ( g_phyFuns_instance = 0x3ffffd94 ); +PROVIDE ( phy_get_romfuncs = 0x4000a88c ); +PROVIDE ( rom_read_hw_noisefloor = 0x40009c38 ); +PROVIDE ( rom_phy_disable_low_rate = 0x4000a2b8 ); +PROVIDE ( rom_phy_enable_low_rate = 0x4000a280 ); +PROVIDE ( intr_matrix_set = 0x4000f1d0 ); + +/* from esp32s2.rom.newlib-funcs.ld */ +strncpy = 0x40007f20; +strcpy = 0x40007cfc; +strncmp = 0x4001ae64; + +/* from esp32s3.rom.libgcc.ld*/ +__popcountsi2 = 0x40008fa8; diff --git a/src/binary/include_esp32s2.rs b/src/binary/include_esp32s2.rs index 6e50ad8a..ff066422 100644 --- a/src/binary/include_esp32s2.rs +++ b/src/binary/include_esp32s2.rs @@ -1,6 +1,11 @@ /* automatically generated by rust-bindgen 0.59.2 */ -#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,dead_code)] +#![allow( + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + dead_code +)] #[repr(C)] #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] diff --git a/src/binary/mod.rs b/src/binary/mod.rs index 305d9be8..70a05fc7 100644 --- a/src/binary/mod.rs +++ b/src/binary/mod.rs @@ -4,4 +4,5 @@ pub mod c_types; #[cfg_attr(feature = "esp32c3", path = "include_esp32c3.rs")] #[cfg_attr(feature = "esp32", path = "include_esp32.rs")] #[cfg_attr(feature = "esp32s3", path = "include_esp32s3.rs")] +#[cfg_attr(feature = "esp32s2", path = "include_esp32s2.rs")] pub mod include; diff --git a/src/common_adapter/common_adapter_esp32s2.rs b/src/common_adapter/common_adapter_esp32s2.rs new file mode 100644 index 00000000..80127332 --- /dev/null +++ b/src/common_adapter/common_adapter_esp32s2.rs @@ -0,0 +1,218 @@ +use super::phy_init_data::PHY_INIT_DATA_DEFAULT; +use crate::binary::include::*; +use esp32s2_hal::prelude::ram; +use log::trace; + +pub(crate) unsafe extern "C" fn phy_enable() { + // quite some code needed here + trace!("phy_enable - not fully implemented"); + + static mut G_IS_PHY_CALIBRATED: bool = false; + + let mut cal_data: [u8; core::mem::size_of::()] = + [0u8; core::mem::size_of::()]; + + critical_section::with(|_| { + phy_enable_clock(); + // phy_set_wifi_mode_only(!crate::wifi::BLE_ENABLED); + + if G_IS_PHY_CALIBRATED == false { + let init_data = &PHY_INIT_DATA_DEFAULT; + + register_chipv7_phy( + init_data, + &mut cal_data as *mut _ as *mut crate::binary::include::esp_phy_calibration_data_t, + esp_phy_calibration_mode_t_PHY_RF_CAL_FULL, + ); + + G_IS_PHY_CALIBRATED = true; + } else { + trace!("implement phy_digital_regs_load"); + phy_wakeup_init(); + //phy_digital_regs_load(); + /* + static inline void phy_digital_regs_load(void) + { + if (g_phy_digital_regs_mem != NULL) + { + phy_dig_reg_backup(false, g_phy_digital_regs_mem); + } + } + */ + } + + #[cfg(feature = "ble")] + { + extern "C" { + fn coex_pti_v2(); + } + coex_pti_v2(); + } + }); +} + +pub(crate) unsafe fn phy_enable_clock() { + trace!("phy_enable_clock"); + const SYSTEM_WIFI_CLK_EN_REG: u32 = 0x3f426000 + 0x090; + critical_section::with(|_| { + (SYSTEM_WIFI_CLK_EN_REG as *mut u32).write_volatile(u32::MAX); + }); + + trace!("phy_enable_clock done!"); +} + +pub(crate) unsafe extern "C" fn read_mac( + mac: *mut u8, + type_: u32, +) -> crate::binary::c_types::c_int { + trace!("read_mac {:p} {}", mac, type_); + + let mut regval = [0u32; 2]; + let data = ®val as *const _ as *const u8; + regval[0] = ((0x3f41A000 + 0x44) as *const u32).read_volatile(); + regval[1] = ((0x3f41A000 + 0x48) as *const u32).read_volatile(); + + for i in 0..6 { + mac.offset(i) + .write_volatile(data.offset(5 - i).read_volatile()); + } + + /* ESP_MAC_WIFI_SOFTAP */ + if type_ == 1 { + let tmp = mac.offset(0).read_volatile(); + for i in 0..64 { + mac.offset(0).write_volatile(tmp | 0x02); + mac.offset(0) + .write_volatile(mac.offset(0).read_volatile() ^ (i << 2)); + + if mac.offset(0).read_volatile() != tmp { + break; + } + } + } + + // ESP_MAC_BT + if type_ == 2 { + let tmp = mac.offset(0).read_volatile(); + for i in 0..64 { + mac.offset(0).write_volatile(tmp | 0x02); + mac.offset(0) + .write_volatile(mac.offset(0).read_volatile() ^ (i << 2)); + + if mac.offset(0).read_volatile() != tmp { + break; + } + } + + mac.offset(5) + .write_volatile(mac.offset(5).read_volatile() + 1); + } + + 0 +} + +pub(crate) fn init_clocks() { + log::warn!("init clocks"); + + const RTC_CNTL_DIG_PWC_REG: u32 = DR_REG_RTCCNTL_BASE + 0x008C; + const DR_REG_RTCCNTL_BASE: u32 = 0x3f408000; + const RTC_CNTL_DIG_ISO_REG: u32 = DR_REG_RTCCNTL_BASE + 0x0090; + + const RTC_CNTL_WIFI_FORCE_PD: u32 = 1 << 17; + const RTC_CNTL_WIFI_FORCE_ISO: u32 = 1 << 28; + unsafe { + (RTC_CNTL_DIG_PWC_REG as *mut u32).write_volatile( + (RTC_CNTL_DIG_PWC_REG as *mut u32).read_volatile() & !RTC_CNTL_WIFI_FORCE_PD, + ); + + (RTC_CNTL_DIG_ISO_REG as *mut u32).write_volatile( + (RTC_CNTL_DIG_ISO_REG as *mut u32).read_volatile() & !RTC_CNTL_WIFI_FORCE_ISO, + ); + } + + // unsafe { + // // PERIP_CLK_EN0 + // ((0x3f426000 + 0x8c) as *mut u32).write_volatile(0xffffffff); + // // PERIP_CLK_EN1 + // ((0x3f426000 + 0x90) as *mut u32).write_volatile(0xffffffff); + // } + + // // APB_CTRL_WIFI_CLK_EN_REG + // unsafe { + // ((0x3f426000 + 0x90) as *mut u32).write_volatile(0xffffffff); + // } +} + +/**************************************************************************** + * Name: phy_enter_critical + * + * Description: + * Enter critical state + * + * Input Parameters: + * None + * + * Returned Value: + * CPU PS value + * + ****************************************************************************/ +#[ram] +#[no_mangle] +unsafe extern "C" fn phy_enter_critical() -> u32 { + trace!("phy_enter_critical"); + + core::mem::transmute(critical_section::acquire()) +} + +/**************************************************************************** + * Name: phy_exit_critical + * + * Description: + * Exit from critical state + * + * Input Parameters: + * level - CPU PS value + * + * Returned Value: + * None + * + ****************************************************************************/ +#[ram] +#[no_mangle] +unsafe extern "C" fn phy_exit_critical(level: u32) { + trace!("phy_exit_critical {}", level); + + critical_section::release(core::mem::transmute(level)); +} + +#[no_mangle] +unsafe extern "C" fn abort() { + trace!("misc_nvs_deinit") +} + +#[no_mangle] +unsafe extern "C" fn misc_nvs_deinit() { + trace!("misc_nvs_deinit") +} + +#[no_mangle] +unsafe extern "C" fn misc_nvs_init() -> i32 { + trace!("misc_nvs_init"); + 0 +} + +#[no_mangle] +unsafe extern "C" fn misc_nvs_restore() -> i32 { + todo!("misc_nvs_restore") +} + +#[no_mangle] +static mut g_log_mod: i32 = 0; + +#[no_mangle] +static mut g_log_level: i32 = 0; + +#[no_mangle] +pub static mut g_misc_nvs: &u32 = unsafe { &NVS }; + +pub static mut NVS: u32 = 0; diff --git a/src/common_adapter/mod.rs b/src/common_adapter/mod.rs index c2b92cf4..28a0baea 100644 --- a/src/common_adapter/mod.rs +++ b/src/common_adapter/mod.rs @@ -7,30 +7,29 @@ use log::trace; use crate::compat::common::*; -#[cfg(feature = "esp32")] -use esp32_hal::Rng; -#[cfg(feature = "esp32c3")] -use esp32c3_hal::Rng; -#[cfg(feature = "esp32s3")] -use esp32s3_hal::Rng; - #[cfg(feature = "esp32")] use esp32_hal as hal; #[cfg(feature = "esp32c3")] use esp32c3_hal as hal; +#[cfg(feature = "esp32s2")] +use esp32s2_hal as hal; #[cfg(feature = "esp32s3")] use esp32s3_hal as hal; +use hal::Rng; + use hal::macros::ram; #[cfg_attr(feature = "esp32c3", path = "common_adapter_esp32c3.rs")] #[cfg_attr(feature = "esp32", path = "common_adapter_esp32.rs")] #[cfg_attr(feature = "esp32s3", path = "common_adapter_esp32s3.rs")] +#[cfg_attr(feature = "esp32s2", path = "common_adapter_esp32s2.rs")] pub(crate) mod chip_specific; #[cfg_attr(feature = "esp32c3", path = "phy_init_data_esp32c3.rs")] #[cfg_attr(feature = "esp32", path = "phy_init_data_esp32.rs")] #[cfg_attr(feature = "esp32s3", path = "phy_init_data_esp32s3.rs")] +#[cfg_attr(feature = "esp32s2", path = "phy_init_data_esp32s2.rs")] pub(crate) mod phy_init_data; pub(crate) static mut RANDOM_GENERATOR: Option = None; diff --git a/src/common_adapter/phy_init_data_esp32s2.rs b/src/common_adapter/phy_init_data_esp32s2.rs new file mode 100644 index 00000000..055929a5 --- /dev/null +++ b/src/common_adapter/phy_init_data_esp32s2.rs @@ -0,0 +1,146 @@ +use crate::binary::include::esp_phy_init_data_t; + +const CONFIG_ESP_PHY_MAX_TX_POWER: u8 = 20; + +const fn limit(val: u8, low: u8, high: u8) -> u8 { + if val < low { + low + } else if val > high { + high + } else { + val + } +} + +pub(crate) static PHY_INIT_DATA_DEFAULT: esp_phy_init_data_t = esp_phy_init_data_t { + params: [ + 0x80, + 0x00, + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x4E), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x4E), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x44), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x44), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x48), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x44), + limit(CONFIG_ESP_PHY_MAX_TX_POWER * 4, 0, 0x42), + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0xf1, + ], +}; diff --git a/src/compat/common.rs b/src/compat/common.rs index a6fe7436..04d4fbb2 100644 --- a/src/compat/common.rs +++ b/src/compat/common.rs @@ -105,13 +105,18 @@ impl Write for StrBuf { } pub unsafe extern "C" fn syslog(_priority: u32, format: *const u8, mut args: VaListImpl) { - #[cfg(feature = "wifi_logs")] + #[cfg(all(feature = "wifi_logs", feature = "esp32c3"))] { let mut buf = [0u8; 512]; vsnprintf(&mut buf as *mut u8, 511, format, args); let res_str = StrBuf::from(&buf as *const u8); info!("{}", res_str.as_str_ref()); } + #[cfg(all(feature = "wifi_logs", not(feature = "esp32c3")))] + { + let res_str = StrBuf::from(format); + info!("{}", res_str.as_str_ref()); + } } pub(crate) unsafe fn vsnprintf( diff --git a/src/lib.rs b/src/lib.rs index 28097be9..4e2c9081 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ use esp32_hal as hal; use esp32c3_hal as hal; #[cfg(feature = "esp32c3")] use esp32c3_hal::systimer::{Alarm, Target}; +#[cfg(feature = "esp32s2")] +use esp32s2_hal as hal; #[cfg(feature = "esp32s3")] use esp32s3_hal as hal; @@ -32,6 +34,7 @@ pub mod preempt; #[cfg_attr(feature = "esp32", path = "timer_esp32.rs")] #[cfg_attr(feature = "esp32c3", path = "timer_esp32c3.rs")] #[cfg_attr(feature = "esp32s3", path = "timer_esp32s3.rs")] +#[cfg_attr(feature = "esp32s2", path = "timer_esp32s2.rs")] pub mod timer; #[cfg(feature = "wifi")] @@ -146,7 +149,7 @@ pub enum InitializationError { WrongClockConfig, } -#[cfg(any(feature = "esp32", feature = "esp32s3"))] +#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] /// Initialize for using WiFi / BLE /// This will initialize internals and also initialize WiFi and BLE pub fn initialize( diff --git a/src/timer_esp32s2.rs b/src/timer_esp32s2.rs new file mode 100644 index 00000000..b844b690 --- /dev/null +++ b/src/timer_esp32s2.rs @@ -0,0 +1,101 @@ +use core::cell::RefCell; + +use atomic_polyfill::{AtomicU64, Ordering}; +use critical_section::Mutex; +use esp32s2_hal::{ + interrupt, + pac::{self, TIMG1}, + prelude::_embedded_hal_timer_CountDown, + timer::{Timer, Timer0}, +}; +use log::trace; +use xtensa_lx_rt::exception::Context; + +use crate::preempt::preempt::task_switch; +use esp32s2_hal::macros::interrupt; + +pub const TICKS_PER_SECOND: u64 = 40_000_000; + +#[cfg(debug_assertions)] +const TIMER_DELAY: fugit::MicrosDurationU64 = fugit::MicrosDurationU64::micros(4000); +#[cfg(not(debug_assertions))] +const TIMER_DELAY: fugit::MicrosDurationU64 = fugit::MicrosDurationU64::micros(500); + +static TIMER1: Mutex>>>> = Mutex::new(RefCell::new(None)); + +static TIME: AtomicU64 = AtomicU64::new(0); + +pub fn get_systimer_count() -> u64 { + TIME.load(Ordering::Relaxed) + read_timer_value() +} + +#[inline(always)] +fn read_timer_value() -> u64 { + let value = xtensa_lx::timer::get_cycle_count() as u64; + value * 40_000_000 / 240_000_000 +} + +pub fn setup_timer_isr(timg1_timer0: Timer>) { + let mut timer1 = timg1_timer0; + interrupt::enable(pac::Interrupt::TG1_T0_LEVEL, interrupt::Priority::Priority2).unwrap(); + + #[cfg(feature = "wifi")] + interrupt::enable(pac::Interrupt::WIFI_MAC, interrupt::Priority::Priority1).unwrap(); + + timer1.listen(); + timer1.start(TIMER_DELAY.convert()); + critical_section::with(|cs| { + TIMER1.borrow_ref_mut(cs).replace(timer1); + }); + + xtensa_lx::timer::set_ccompare0(0xffffffff); + + unsafe { + xtensa_lx::interrupt::disable(); + xtensa_lx::interrupt::enable_mask( + 1 << 6 + | xtensa_lx_rt::interrupt::CpuInterruptLevel::Level2.mask() + | xtensa_lx_rt::interrupt::CpuInterruptLevel::Level6.mask(), + ); + } + + while unsafe { + crate::preempt::preempt::FIRST_SWITCH.load(core::sync::atomic::Ordering::Relaxed) + } {} +} + +#[allow(non_snake_case)] +#[no_mangle] +fn Timer0(_level: u32) { + TIME.fetch_add(0x1_0000_0000 * 40_000_000 / 240_000_000, Ordering::Relaxed); + + xtensa_lx::timer::set_ccompare0(0xffffffff); +} + +#[cfg(feature = "wifi")] +#[interrupt] +fn WIFI_MAC() { + unsafe { + let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1; + trace!("interrupt WIFI_MAC {:p} {:p}", fnc, arg); + + if !fnc.is_null() { + let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc); + fnc(arg); + } + } +} + +#[interrupt] +fn TG1_T0_LEVEL(context: &mut Context) { + task_switch(context); + + critical_section::with(|cs| { + crate::memory_fence::memory_fence(); + + let mut timer = TIMER1.borrow_ref_mut(cs); + let timer = timer.as_mut().unwrap(); + timer.clear_interrupt(); + timer.start(TIMER_DELAY.convert()); + }); +} diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index 79665736..eff42e32 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -14,6 +14,8 @@ use smoltcp::phy::{Device, DeviceCapabilities, RxToken, TxToken}; use esp32_hal as hal; #[cfg(feature = "esp32c3")] use esp32c3_hal as hal; +#[cfg(feature = "esp32s2")] +use esp32s2_hal as hal; #[cfg(feature = "esp32s3")] use esp32s3_hal as hal; @@ -299,13 +301,13 @@ static g_wifi_osi_funcs: wifi_osi_funcs_t = wifi_osi_funcs_t { _coex_schm_curr_phase_get: Some(coex_schm_curr_phase_get), _coex_schm_curr_phase_idx_set: Some(coex_schm_curr_phase_idx_set), _coex_schm_curr_phase_idx_get: Some(coex_schm_curr_phase_idx_get), - #[cfg(any(feature = "esp32c3", feature = "esp32s3"))] + #[cfg(any(feature = "esp32c3", feature = "esp32s3", feature = "esp32s2"))] _slowclk_cal_get: Some(slowclk_cal_get), - #[cfg(feature = "esp32")] + #[cfg(any(feature = "esp32", feature = "esp32s2"))] _phy_common_clock_disable: Some( crate::wifi::os_adapter::os_adapter_chip_specific::phy_common_clock_disable, ), - #[cfg(feature = "esp32")] + #[cfg(any(feature = "esp32", feature = "esp32s2"))] _phy_common_clock_enable: Some( crate::wifi::os_adapter::os_adapter_chip_specific::phy_common_clock_enable, ), diff --git a/src/wifi/os_adapter.rs b/src/wifi/os_adapter.rs index 5ed628fa..8f670a75 100644 --- a/src/wifi/os_adapter.rs +++ b/src/wifi/os_adapter.rs @@ -1,6 +1,7 @@ #[cfg_attr(feature = "esp32c3", path = "os_adapter_esp32c3.rs")] #[cfg_attr(feature = "esp32", path = "os_adapter_esp32.rs")] #[cfg_attr(feature = "esp32s3", path = "os_adapter_esp32s3.rs")] +#[cfg_attr(feature = "esp32s2", path = "os_adapter_esp32s2.rs")] pub(crate) mod os_adapter_chip_specific; use log::{debug, trace}; @@ -1910,7 +1911,7 @@ pub unsafe extern "C" fn coex_pti_get(event: u32, pti: *mut u8) -> crate::binary 0 } -#[cfg(feature = "esp32")] +#[cfg(any(feature = "esp32", feature = "esp32s2"))] pub unsafe extern "C" fn coex_pti_get(event: u32, pti: *mut u8) -> crate::binary::c_types::c_int { log::debug!("coex_pti_get {} {:p}", event, pti); 0 diff --git a/src/wifi/os_adapter_esp32s2.rs b/src/wifi/os_adapter_esp32s2.rs new file mode 100644 index 00000000..add78940 --- /dev/null +++ b/src/wifi/os_adapter_esp32s2.rs @@ -0,0 +1,55 @@ +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(non_snake_case)] +use log::trace; + +pub(crate) fn chip_ints_on(mask: u32) { + trace!("chip_ints_on esp32"); + unsafe { + xtensa_lx::interrupt::enable_mask(1 << 0); + } +} + +pub(crate) unsafe extern "C" fn wifi_int_disable( + wifi_int_mux: *mut crate::binary::c_types::c_void, +) -> u32 { + trace!("wifi_int_disable() esp32"); + core::mem::transmute(critical_section::acquire()) +} + +pub(crate) unsafe extern "C" fn wifi_int_restore( + wifi_int_mux: *mut crate::binary::c_types::c_void, + tmp: u32, +) { + trace!("wifi_int_restore() esp32"); + critical_section::release(core::mem::transmute(tmp)) +} + +pub(crate) unsafe extern "C" fn set_intr( + cpu_no: i32, + intr_source: u32, + intr_num: u32, + intr_prio: i32, +) { + extern "C" { + fn intr_matrix_set(cpu_no: u32, model_num: u32, intr_num: u32); + } + // Force to bind WiFi interrupt to CPU0 + intr_matrix_set(0, intr_source, intr_num); +} + +pub(crate) unsafe extern "C" fn wifi_clock_enable() { + log::debug!("wifi_clock_enable not implemented"); +} + +pub(crate) unsafe extern "C" fn wifi_clock_disable() { + log::debug!("wifi_clock_disable not implemented"); +} + +pub(crate) unsafe extern "C" fn phy_common_clock_disable() { + trace!("phy_common_clock_disable - not implemented"); +} + +pub(crate) unsafe extern "C" fn phy_common_clock_enable() { + trace!("phy_common_clock_enable - not implemented"); +}