diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 82cc63955..eea60405f 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -46,6 +46,8 @@ jobs: - 'esp-lp-hal/**' esp-metadata: - 'esp-metadata/**' + esp-phy: + - 'esp-phy/**' esp-preempt: - 'esp-preempt/**' esp-println: @@ -137,6 +139,14 @@ jobs: skipLabels: "skip-changelog" missingUpdateErrorMessage: "Please add a changelog entry in the esp-lp-hal/CHANGELOG.md file." + - name: Check that changelog updated (esp-phy) + if: steps.changes.outputs.esp-phy == 'true' + uses: dangoslen/changelog-enforcer@v3 + with: + changeLogPath: esp-phy/CHANGELOG.md + skipLabels: "skip-changelog" + missingUpdateErrorMessage: "Please add a changelog entry in the esp-phy/CHANGELOG.md file." + - name: Check that changelog updated (esp-preempt) if: steps.changes.outputs.esp-preempt == 'true' uses: dangoslen/changelog-enforcer@v3 diff --git a/.lycheeignore b/.lycheeignore index c738861fd..d0a9595ef 100644 --- a/.lycheeignore +++ b/.lycheeignore @@ -22,7 +22,8 @@ releases/tag/$ img\.shields\.io/badge/MSRV- # TODO: remove once released +docs\.espressif\.com/projects/rust/esp-phy/latest/ docs\.espressif\.com/projects/rust/esp-preempt/latest/ docs\.espressif\.com/projects/rust/esp-radio-preempt-driver/latest/ docs\.espressif\.com/projects/rust/esp-radio/latest/ -docs\.espressif\.com/projects/rust/esp-sync/latest/ \ No newline at end of file +docs\.espressif\.com/projects/rust/esp-sync/latest/ diff --git a/Cargo.toml b/Cargo.toml index e419c6f6c..e49ef4a49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ exclude = [ "esp-lp-hal", "esp-metadata", "esp-metadata-generated", + "esp-phy", "esp-println", "esp-preempt", "esp-radio-preempt-driver", diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index a17df633f..3fbdad540 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Expose cache line configuration (#3946) - ESP32: Expose `psram_vaddr_mode` via `PsramConfig` (#3990) - ESP32-S3: Expose more `Camera` config options (#3996) +- Functions to query chip revision for every chip (#3892) - ESP32-S3: Add RtcI2c driver (#0000) - `ShaBackend, ShaContext`: Work-queue based SHA driver (#4013) - I2S: `i2s::master::Config` with support for more TDM mode standards (#3985) diff --git a/esp-hal/README.md b/esp-hal/README.md index d4b9d4889..9064373ec 100644 --- a/esp-hal/README.md +++ b/esp-hal/README.md @@ -99,6 +99,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a | WIFI | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | | Bluetooth | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | | IEEE 802.15.4 | | | | ⚒️ | ⚒️ | | | +| PHY | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | * Empty cell: not available * ❌: Not supported diff --git a/esp-hal/src/clock/mod.rs b/esp-hal/src/clock/mod.rs index 3a4d20e38..e76ae01ba 100644 --- a/esp-hal/src/clock/mod.rs +++ b/esp-hal/src/clock/mod.rs @@ -1431,7 +1431,7 @@ impl Drop for PhyClockGuard<'_> { #[cfg(any(bt, ieee802154, wifi))] #[instability::unstable] -/// This trait provides common functionality for all +/// This trait provides common clock functionality for all modem peripherals. pub trait ModemClockController<'d>: Sealed + 'd { /// Enable the modem clock for this controller. fn enable_modem_clock(&mut self, enable: bool); diff --git a/esp-hal/src/efuse/esp32s2/mod.rs b/esp-hal/src/efuse/esp32s2/mod.rs index ba3e7e532..f3cb82d78 100644 --- a/esp-hal/src/efuse/esp32s2/mod.rs +++ b/esp-hal/src/efuse/esp32s2/mod.rs @@ -15,6 +15,25 @@ impl super::Efuse { pub fn rwdt_multiplier() -> u8 { Self::read_field_le::(WDT_DELAY_SEL) } + + /// Returns the major hardware revision + pub fn major_chip_version() -> u8 { + Self::read_field_le(WAFER_VERSION_MAJOR) + } + + /// Returns the minor hardware revision + pub fn minor_chip_version() -> u8 { + Self::read_field_le::(WAFER_VERSION_MINOR_HI) << 3 + | Self::read_field_le::(WAFER_VERSION_MINOR_LO) + } + + /// Returns the hardware revision + /// + /// The chip version is calculated using the following + /// formula: MAJOR * 100 + MINOR. (if the result is 1, then version is v0.1) + pub fn chip_revision() -> u16 { + Self::major_chip_version() as u16 * 100 + Self::minor_chip_version() as u16 + } } #[derive(Debug, Clone, Copy, strum::FromRepr)] diff --git a/esp-hal/src/efuse/esp32s3/mod.rs b/esp-hal/src/efuse/esp32s3/mod.rs index de13be012..5e79103b3 100644 --- a/esp-hal/src/efuse/esp32s3/mod.rs +++ b/esp-hal/src/efuse/esp32s3/mod.rs @@ -140,6 +140,25 @@ impl super::Efuse { adc2_vol[atten] }) } + + /// Returns the major hardware revision + pub fn major_chip_version() -> u8 { + Self::read_field_le(WAFER_VERSION_MAJOR) + } + + /// Returns the minor hardware revision + pub fn minor_chip_version() -> u8 { + Self::read_field_le::(WAFER_VERSION_MINOR_HI) << 3 + | Self::read_field_le::(WAFER_VERSION_MINOR_LO) + } + + /// Returns the hardware revision + /// + /// The chip version is calculated using the following + /// formula: MAJOR * 100 + MINOR. (if the result is 1, then version is v0.1) + pub fn chip_revision() -> u16 { + Self::major_chip_version() as u16 * 100 + Self::minor_chip_version() as u16 + } } #[derive(Debug, Clone, Copy, strum::FromRepr)] diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index c903db5d1..5443cdd55 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -248,6 +248,7 @@ impl Chip { "ulp_fsm", "wifi", "bt", + "phy", "adc_adc1", "adc_adc2", "dac_dac1", @@ -293,6 +294,7 @@ impl Chip { "rsa_memory_size_bytes=\"512\"", "timergroup_timg_has_timer1", "uart_ram_size=\"128\"", + "phy_combo_module", "has_dram_region", ], cfgs: &[ @@ -404,6 +406,7 @@ impl Chip { "cargo:rustc-cfg=ulp_fsm", "cargo:rustc-cfg=wifi", "cargo:rustc-cfg=bt", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=adc_adc2", "cargo:rustc-cfg=dac_dac1", @@ -449,6 +452,7 @@ impl Chip { "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=uart_ram_size=\"128\"", + "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=has_dram_region", ], }, @@ -532,6 +536,7 @@ impl Chip { "uart", "wifi", "bt", + "phy", "adc_adc1", "i2c_master_i2c0", "spi_master_spi2", @@ -571,6 +576,7 @@ impl Chip { "timergroup_default_wdt_clock_source=\"0\"", "timergroup_default_wdt_clock_source_is_set", "uart_ram_size=\"128\"", + "phy_combo_module", "has_dram_region", ], cfgs: &[ @@ -650,6 +656,7 @@ impl Chip { "cargo:rustc-cfg=uart", "cargo:rustc-cfg=wifi", "cargo:rustc-cfg=bt", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=spi_master_spi2", @@ -689,6 +696,7 @@ impl Chip { "cargo:rustc-cfg=timergroup_default_wdt_clock_source=\"0\"", "cargo:rustc-cfg=timergroup_default_wdt_clock_source_is_set", "cargo:rustc-cfg=uart_ram_size=\"128\"", + "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=has_dram_region", ], }, @@ -786,6 +794,7 @@ impl Chip { "usb_serial_jtag", "wifi", "bt", + "phy", "adc_adc1", "adc_adc2", "i2c_master_i2c0", @@ -840,6 +849,9 @@ impl Chip { "timergroup_default_wdt_clock_source=\"0\"", "timergroup_default_wdt_clock_source_is_set", "uart_ram_size=\"128\"", + "phy_combo_module", + "phy_backed_up_digital_register_count=\"21\"", + "phy_backed_up_digital_register_count_is_set", "has_dram_region", ], cfgs: &[ @@ -933,6 +945,7 @@ impl Chip { "cargo:rustc-cfg=usb_serial_jtag", "cargo:rustc-cfg=wifi", "cargo:rustc-cfg=bt", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=adc_adc2", "cargo:rustc-cfg=i2c_master_i2c0", @@ -987,6 +1000,9 @@ impl Chip { "cargo:rustc-cfg=timergroup_default_wdt_clock_source=\"0\"", "cargo:rustc-cfg=timergroup_default_wdt_clock_source_is_set", "cargo:rustc-cfg=uart_ram_size=\"128\"", + "cargo:rustc-cfg=phy_combo_module", + "cargo:rustc-cfg=phy_backed_up_digital_register_count=\"21\"", + "cargo:rustc-cfg=phy_backed_up_digital_register_count_is_set", "cargo:rustc-cfg=has_dram_region", ], }, @@ -1136,6 +1152,7 @@ impl Chip { "wifi", "bt", "ieee802154", + "phy", "adc_adc1", "i2c_master_i2c0", "spi_master_spi2", @@ -1195,6 +1212,7 @@ impl Chip { "uart_ram_size=\"128\"", "lp_uart_ram_size=\"32\"", "wifi_has_wifi6", + "phy_combo_module", "has_dram_region", ], cfgs: &[ @@ -1340,6 +1358,7 @@ impl Chip { "cargo:rustc-cfg=wifi", "cargo:rustc-cfg=bt", "cargo:rustc-cfg=ieee802154", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=spi_master_spi2", @@ -1399,6 +1418,7 @@ impl Chip { "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=lp_uart_ram_size=\"32\"", "cargo:rustc-cfg=wifi_has_wifi6", + "cargo:rustc-cfg=phy_combo_module", "cargo:rustc-cfg=has_dram_region", ], }, @@ -1524,6 +1544,7 @@ impl Chip { "usb_serial_jtag", "bt", "ieee802154", + "phy", "adc_adc1", "i2c_master_i2c0", "i2c_master_i2c1", @@ -1702,6 +1723,7 @@ impl Chip { "cargo:rustc-cfg=usb_serial_jtag", "cargo:rustc-cfg=bt", "cargo:rustc-cfg=ieee802154", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=i2c_master_i2c0", "cargo:rustc-cfg=i2c_master_i2c1", @@ -1873,6 +1895,7 @@ impl Chip { "ulp_riscv", "usb_otg", "wifi", + "phy", "adc_adc1", "adc_adc2", "dac_dac1", @@ -2041,6 +2064,7 @@ impl Chip { "cargo:rustc-cfg=ulp_riscv", "cargo:rustc-cfg=usb_otg", "cargo:rustc-cfg=wifi", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=adc_adc2", "cargo:rustc-cfg=dac_dac1", @@ -2230,6 +2254,7 @@ impl Chip { "usb_serial_jtag", "wifi", "bt", + "phy", "adc_adc1", "adc_adc2", "i2c_master_i2c0", @@ -2286,6 +2311,9 @@ impl Chip { "timergroup_default_clock_source=\"0\"", "timergroup_default_clock_source_is_set", "uart_ram_size=\"128\"", + "phy_combo_module", + "phy_backed_up_digital_register_count=\"21\"", + "phy_backed_up_digital_register_count_is_set", "has_dram_region", ], cfgs: &[ @@ -2413,6 +2441,7 @@ impl Chip { "cargo:rustc-cfg=usb_serial_jtag", "cargo:rustc-cfg=wifi", "cargo:rustc-cfg=bt", + "cargo:rustc-cfg=phy", "cargo:rustc-cfg=adc_adc1", "cargo:rustc-cfg=adc_adc2", "cargo:rustc-cfg=i2c_master_i2c0", @@ -2469,6 +2498,9 @@ impl Chip { "cargo:rustc-cfg=timergroup_default_clock_source=\"0\"", "cargo:rustc-cfg=timergroup_default_clock_source_is_set", "cargo:rustc-cfg=uart_ram_size=\"128\"", + "cargo:rustc-cfg=phy_combo_module", + "cargo:rustc-cfg=phy_backed_up_digital_register_count=\"21\"", + "cargo:rustc-cfg=phy_backed_up_digital_register_count_is_set", "cargo:rustc-cfg=has_dram_region", ], }, @@ -2616,6 +2648,7 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(i2c_master_separate_filter_config_registers)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_i2c0_data_register_ahb_address_is_set)"); println!("cargo:rustc-check-cfg=cfg(timergroup_timg_has_timer1)"); + println!("cargo:rustc-check-cfg=cfg(phy_combo_module)"); println!("cargo:rustc-check-cfg=cfg(esp32c2)"); println!("cargo:rustc-check-cfg=cfg(riscv)"); println!("cargo:rustc-check-cfg=cfg(single_core)"); @@ -2683,6 +2716,7 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(aes_dma_mode_cfb128)"); println!("cargo:rustc-check-cfg=cfg(aes_has_split_text_registers)"); println!("cargo:rustc-check-cfg=cfg(assist_debug_has_region_monitor)"); + println!("cargo:rustc-check-cfg=cfg(phy_backed_up_digital_register_count_is_set)"); println!("cargo:rustc-check-cfg=cfg(esp32c6)"); println!("cargo:rustc-check-cfg=cfg(soc_has_atomic)"); println!("cargo:rustc-check-cfg=cfg(soc_has_hp_apm)"); @@ -2806,6 +2840,7 @@ impl Config { "cargo:rustc-check-cfg=cfg(timergroup_default_wdt_clock_source, values(\"0\",\"1\",\"2\"))" ); println!("cargo:rustc-check-cfg=cfg(soc_xtal_frequency, values(\"40\",\"32\"))"); + println!("cargo:rustc-check-cfg=cfg(phy_backed_up_digital_register_count, values(\"21\"))"); println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_fifo_size, values(\"16\"))"); println!("cargo:rustc-check-cfg=cfg(lp_uart_ram_size, values(\"32\"))"); for cfg in self.cfgs { diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index 6de154f31..07eb18418 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -225,6 +225,9 @@ macro_rules! property { ("wifi.has_wifi6") => { false }; + ("phy.combo_module") => { + true + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32c2.rs b/esp-metadata-generated/src/_generated_esp32c2.rs index 75434c5b2..fda30f88f 100644 --- a/esp-metadata-generated/src/_generated_esp32c2.rs +++ b/esp-metadata-generated/src/_generated_esp32c2.rs @@ -198,6 +198,9 @@ macro_rules! property { ("wifi.has_wifi6") => { false }; + ("phy.combo_module") => { + true + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32c3.rs b/esp-metadata-generated/src/_generated_esp32c3.rs index ad98c027f..44150dd0d 100644 --- a/esp-metadata-generated/src/_generated_esp32c3.rs +++ b/esp-metadata-generated/src/_generated_esp32c3.rs @@ -234,6 +234,15 @@ macro_rules! property { ("wifi.has_wifi6") => { false }; + ("phy.combo_module") => { + true + }; + ("phy.backed_up_digital_register_count") => { + 21 + }; + ("phy.backed_up_digital_register_count", str) => { + stringify!(21) + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32c6.rs b/esp-metadata-generated/src/_generated_esp32c6.rs index c8cd8bd06..7c95176dd 100644 --- a/esp-metadata-generated/src/_generated_esp32c6.rs +++ b/esp-metadata-generated/src/_generated_esp32c6.rs @@ -246,6 +246,9 @@ macro_rules! property { ("wifi.has_wifi6") => { true }; + ("phy.combo_module") => { + true + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 272f50a7b..30a3fbf29 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -231,6 +231,9 @@ macro_rules! property { ("uart.ram_size", str) => { stringify!(128) }; + ("phy.combo_module") => { + false + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32s2.rs b/esp-metadata-generated/src/_generated_esp32s2.rs index 2b2a9f5cc..977240fc4 100644 --- a/esp-metadata-generated/src/_generated_esp32s2.rs +++ b/esp-metadata-generated/src/_generated_esp32s2.rs @@ -234,6 +234,9 @@ macro_rules! property { ("wifi.has_wifi6") => { false }; + ("phy.combo_module") => { + false + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata-generated/src/_generated_esp32s3.rs b/esp-metadata-generated/src/_generated_esp32s3.rs index 770295a24..9c4023bd1 100644 --- a/esp-metadata-generated/src/_generated_esp32s3.rs +++ b/esp-metadata-generated/src/_generated_esp32s3.rs @@ -228,6 +228,15 @@ macro_rules! property { ("wifi.has_wifi6") => { false }; + ("phy.combo_module") => { + true + }; + ("phy.backed_up_digital_register_count") => { + 21 + }; + ("phy.backed_up_digital_register_count", str) => { + stringify!(21) + }; } /// Macro to get the address range of the given memory region. #[macro_export] diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index a2feca822..0cd4cfe5b 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -677,3 +677,5 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] [device.bt] +[device.phy] +combo_module = true diff --git a/esp-metadata/devices/esp32c2.toml b/esp-metadata/devices/esp32c2.toml index d36592214..9f278a23e 100644 --- a/esp-metadata/devices/esp32c2.toml +++ b/esp-metadata/devices/esp32c2.toml @@ -306,3 +306,5 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] [device.bt] +[device.phy] +combo_module = true diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index e8e1e58dd..0f10f33a4 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -373,3 +373,6 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] [device.bt] +[device.phy] +combo_module = true +backed_up_digital_register_count = 21 diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 00af5361c..8418a02b5 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -544,3 +544,5 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.bt] [device.ieee802154] +[device.phy] +combo_module = true diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 874b9f463..9b6020999 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -451,3 +451,4 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.bt] [device.ieee802154] +[device.phy] diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index 70c9712f6..867cc9aaa 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -505,3 +505,4 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] +[device.phy] diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index 955e3de5a..ed615d065 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -681,3 +681,6 @@ apb_cycle_wait_num = 16 # TODO ## Radio [device.wifi] [device.bt] +[device.phy] +combo_module = true +backed_up_digital_register_count = 21 diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index 0af1bbb97..193604a58 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -619,4 +619,14 @@ driver_configs![ name: "IEEE 802.15.4", properties: {} }, + PhyProperties { + driver: phy, + name: "PHY", + properties: { + #[serde(default)] + combo_module: bool, + #[serde(default)] + backed_up_digital_register_count: Option, + } + }, ]; diff --git a/esp-phy/CHANGELOG.md b/esp-phy/CHANGELOG.md new file mode 100644 index 000000000..679cb5a31 --- /dev/null +++ b/esp-phy/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial release (#3892) diff --git a/esp-phy/Cargo.toml b/esp-phy/Cargo.toml new file mode 100644 index 000000000..6e5331536 --- /dev/null +++ b/esp-phy/Cargo.toml @@ -0,0 +1,90 @@ +[package] +name = "esp-phy" +version = "0.0.1" +edition = "2024" +description = "PHY initialization" +documentation = "https://docs.espressif.com/projects/rust/esp-preempt/latest/" +keywords = ["esp32", "espressif", "no-std"] +categories = ["embedded", "hardware-support", "no-std"] +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" + +[package.metadata.espressif] +doc-config = { features = ["esp-hal/unstable", "defmt"] } +check-configs = [ + { features = ["esp-hal/unstable"] }, +] +clippy-configs = [ + { features = ["esp-hal/unstable", "defmt"] }, +] + +[package.metadata.docs.rs] +default-target = "riscv32imac-unknown-none-elf" +features = ["esp32c6"] + +[lib] +bench = false + +[dependencies] +esp-hal = { version = "1.0.0-rc.0", path = "../esp-hal", default-features = false, features = ["requires-unstable"] } +esp-wifi-sys = "0.8.1" +esp-metadata-generated = { version = "0.1.0", path = "../esp-metadata-generated" } +esp-sync = { version = "0.0.0", path = "../esp-sync" } + +cfg-if = "1.0.1" + +defmt = { version = "1.0.1", optional = true } +log-04 = { version = "0.4.27", package = "log", optional = true } +portable-atomic = { version = "1.11.1", default-features = false } + +[build-dependencies] +esp-config = { version = "0.5.0", path = "../esp-config", features = ["build"] } +esp-metadata-generated = { version = "0.1.0", path = "../esp-metadata-generated", features = ["build-script"] } + +[features] +defmt = ["dep:defmt"] +log-04 = ["dep:log-04"] + +# Chip Support Feature Flags +# Target the ESP32-C2. +esp32c2 = [ + "esp-hal/esp32c2", + "esp-wifi-sys/esp32c2", + "esp-metadata-generated/esp32c2", +] +# Target the ESP32-C3. +esp32c3 = [ + "esp-hal/esp32c3", + "esp-wifi-sys/esp32c3", + "esp-metadata-generated/esp32c3", +] +# Target the ESP32-C6. +esp32c6 = [ + "esp-hal/esp32c6", + "esp-wifi-sys/esp32c6", + "esp-metadata-generated/esp32c6", +] +# Target the ESP32-H2. +esp32h2 = [ + "esp-hal/esp32h2", + "esp-wifi-sys/esp32h2", + "esp-metadata-generated/esp32h2", +] +# Target the ESP32. +esp32 = [ + "esp-hal/esp32", + "esp-wifi-sys/esp32", + "esp-metadata-generated/esp32", +] +# Target the ESP32-S2. +esp32s2 = [ + "esp-hal/esp32s2", + "esp-wifi-sys/esp32s2", + "esp-metadata-generated/esp32s2", +] +# Target the ESP32-S3. +esp32s3 = [ + "esp-hal/esp32s3", + "esp-wifi-sys/esp32s3", + "esp-metadata-generated/esp32s3", +] diff --git a/esp-phy/README.md b/esp-phy/README.md new file mode 100644 index 000000000..3047dcb10 --- /dev/null +++ b/esp-phy/README.md @@ -0,0 +1,29 @@ +# esp-phy + +[![Crates.io](https://img.shields.io/crates/v/esp-phy?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-phy) +[![docs.rs](https://img.shields.io/docsrs/esp-phy?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-phy/latest/) +![MSRV](https://img.shields.io/badge/MSRV-1.86.0-blue?labelColor=1C2C2E&style=flat-square) +![Crates.io](https://img.shields.io/crates/l/esp-phy?labelColor=1C2C2E&style=flat-square) +[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) + +This crate implements PHY initialization handling for ESP32 devices. + +## Minimum Supported Rust Version (MSRV) + +This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the +work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/esp-phy/build.rs b/esp-phy/build.rs new file mode 100644 index 000000000..3c09da1b9 --- /dev/null +++ b/esp-phy/build.rs @@ -0,0 +1,29 @@ +use std::error::Error as StdError; + +use esp_config::generate_config_from_yaml_definition; + +fn main() -> Result<(), Box> { + // Load the configuration for the configured device: + let chip = esp_metadata_generated::Chip::from_cargo_feature()?; + + // Define all necessary configuration symbols for the configured device: + chip.define_cfgs(); + + println!("cargo:rerun-if-changed=./esp_config.yml"); + let cfg_yaml = std::fs::read_to_string("./esp_config.yml") + .expect("Failed to read esp_config.yml for esp-phy"); + let _cfg = generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap(); + + let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); + println!("cargo:rustc-link-search={}", out.display()); + + let linker_script = "phy_provides.x"; + let out_file = out.join("libesp-phy.a"); + let _ = std::fs::copy(linker_script, out_file); + println!("cargo:rerun-if-changed={linker_script}"); + // exploit the fact that linkers treat an unknown library format as a linker + // script + println!("cargo:rustc-link-lib=esp-phy"); + + Ok(()) +} diff --git a/esp-phy/esp_config.yml b/esp-phy/esp_config.yml new file mode 100644 index 000000000..56318bee6 --- /dev/null +++ b/esp-phy/esp_config.yml @@ -0,0 +1,19 @@ +crate: esp-phy + +options: + - name: phy_enable_usb + description: "Keeps USB running when using WiFi. + This allows debugging and log messages via USB Serial JTAG. + Turn off for best WiFi performance." + default: + - value: true + + - name: phy_skip_calibration_after_deep_sleep + description: "Use PHY_RF_CAL_NONE after deep sleep." + default: + - value: false + + - name: phy_full_calibration + description: "Use PHY_RF_CAL_FULL instead of PHY_RF_CAL_PARTIAL." + default: + - value: true diff --git a/esp-phy/phy_provides.x b/esp-phy/phy_provides.x new file mode 100644 index 000000000..e30dea557 --- /dev/null +++ b/esp-phy/phy_provides.x @@ -0,0 +1,9 @@ +EXTERN( __esp_phy_enter_critical ); +EXTERN( __esp_phy_exit_critical ); +EXTERN( __esp_phy_esp_dport_access_reg_read ); +EXTERN( __esp_phy_rtc_get_xtal ); + +PROVIDE( phy_enter_critical = __esp_phy_enter_critical ); +PROVIDE( phy_exit_critical = __esp_phy_exit_critical ); +PROVIDE( esp_dport_access_reg_read = __esp_phy_esp_dport_access_reg_read ); +PROVIDE( rtc_get_xtal = __esp_phy_rtc_get_xtal ); diff --git a/esp-phy/src/common_adapter.rs b/esp-phy/src/common_adapter.rs new file mode 100644 index 000000000..54e9c38ca --- /dev/null +++ b/esp-phy/src/common_adapter.rs @@ -0,0 +1,77 @@ +use esp_hal::ram; + +/// ************************************************************************** +/// Name: phy_enter_critical +/// +/// Description: +/// Enter critical state +/// +/// Input Parameters: +/// None +/// +/// Returned Value: +/// CPU PS value +/// +/// ************************************************************************* +#[ram] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_phy_enter_critical() -> u32 { + trace!("phy_enter_critical"); + + unsafe { crate::ESP_PHY_LOCK.acquire().inner() } +} + +/// ************************************************************************** +/// Name: phy_exit_critical +/// +/// Description: +/// Exit from critical state +/// +/// Input Parameters: +/// level - CPU PS value +/// +/// Returned Value: +/// None +/// +/// ************************************************************************* +#[ram] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_phy_exit_critical(level: u32) { + trace!("phy_exit_critical {}", level); + + unsafe { + let token = esp_sync::RestoreState::new(level); + crate::ESP_PHY_LOCK.release(token); + } +} + +/// ************************************************************************** +/// Name: esp_dport_access_reg_read +/// +/// Description: +/// Read regitser value safely in SMP +/// +/// Input Parameters: +/// reg - Register address +/// +/// Returned Value: +/// Register value +/// +/// ************************************************************************* +#[ram] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_phy_esp_dport_access_reg_read(reg: u32) -> u32 { + unsafe { + // trace!("esp_dport_access_reg_read {:x} => {:x}", reg, res); + (reg as *mut u32).read_volatile() + } +} + +#[ram] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_phy_rtc_get_xtal() -> u32 { + use esp_hal::clock::Clock; + + let xtal = esp_hal::clock::RtcClock::xtal_freq(); + xtal.mhz() +} diff --git a/esp-phy/src/fmt.rs b/esp-phy/src/fmt.rs new file mode 100644 index 000000000..4434d6fd7 --- /dev/null +++ b/esp-phy/src/fmt.rs @@ -0,0 +1,312 @@ +#![macro_use] +#![allow(unused_macros)] + +use core::fmt::{Debug, Display, LowerHex}; + +#[collapse_debuginfo(yes)] +macro_rules! assert { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::assert!($($x)*); + } else { + ::core::assert!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! assert_eq { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::assert_eq!($($x)*); + } else { + ::core::assert_eq!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! assert_ne { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::assert_ne!($($x)*); + } else { + ::core::assert_ne!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::debug_assert!($($x)*); + } else { + ::core::debug_assert!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::debug_assert_eq!($($x)*); + } else { + ::core::debug_assert_eq!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::debug_assert_ne!($($x)*); + } else { + ::core::debug_assert_ne!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! todo { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::todo!($($x)*); + } else { + ::core::todo!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! unreachable { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::unreachable!($($x)*); + } else { + ::core::unreachable!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! panic { + ($($x:tt)*) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::panic!($($x)*); + } else { + ::core::panic!($($x)*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::trace!($s $(, $x)*); + } else if #[cfg(feature = "log-04")] { + ::log_04::trace!($s $(, $x)*); + } else { + let _ = ($( & $x ),*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::debug!($s $(, $x)*); + } else if #[cfg(feature = "log-04")] { + ::log_04::debug!($s $(, $x)*); + } else { + let _ = ($( & $x ),*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::info!($s $(, $x)*); + } else if #[cfg(feature = "log-04")] { + ::log_04::info!($s $(, $x)*); + } else { + let _ = ($( & $x ),*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::warn!($s $(, $x)*); + } else if #[cfg(feature = "log-04")] { + ::log_04::warn!($s $(, $x)*); + } else { + let _ = ($( & $x ),*); + } + } + } + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + cfg_if::cfg_if! { + if #[cfg(feature = "defmt")] { + ::defmt::error!($s $(, $x)*); + } else if #[cfg(feature = "log-04")] { + ::log_04::error!($s $(, $x)*); + } else { + let _ = ($( & $x ),*); + } + } + } + }; +} + +#[cfg(feature = "defmt")] +#[collapse_debuginfo(yes)] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +#[collapse_debuginfo(yes)] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + #[allow(unused)] + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} + +/// A way to `{:x?}` format a byte slice which is compatible with `defmt` +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl Debug for Bytes<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl Display for Bytes<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl LowerHex for Bytes<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl defmt::Format for Bytes<'_> { + fn format(&self, fmt: defmt::Formatter<'_>) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/esp-phy/src/lib.rs b/esp-phy/src/lib.rs new file mode 100644 index 000000000..f94ccf4a6 --- /dev/null +++ b/esp-phy/src/lib.rs @@ -0,0 +1,373 @@ +//! PHY initialization handling for chips with a radio. +//! +//! # Usage +//! ## Enabling and Disabling the PHY +//! The [PhyController] trait is implemented for all modem peripherals (`WIFI`, `BT` and +//! `IEEE802154`), that are present for a particular chip. See its documentation for further usage +//! instructions. +//! +//! ## Backing Up and Restoring PHY Calibration Data +//! If the PHY has already been calibrated, you can use [backup_phy_calibration_data] to persist +//! calibration data elsewhere (e.g. in flash). Using [set_phy_calibration_data] you can restore +//! previously persisted calibration data. +//! ## Config Options +#![doc = include_str!(concat!(env!("OUT_DIR"), "/esp_phy_config_table.md"))] +#![no_std] + +// MUST be the first module +mod fmt; + +use esp_hal::clock::{ModemClockController, PhyClockGuard}; +#[cfg(esp32)] +use esp_hal::time::{Duration, Instant}; +use esp_sync::{NonReentrantMutex, RawMutex}; +use esp_wifi_sys::include::*; + +mod common_adapter; +mod phy_init_data; + +pub(crate) mod private { + pub trait Sealed {} +} + +/// Length of the PHY calibration data. +pub const PHY_CALIBRATION_DATA_LENGTH: usize = + core::mem::size_of::(); + +/// Type alias for opaque calibration data. +pub type PhyCalibrationData = [u8; PHY_CALIBRATION_DATA_LENGTH]; + +#[cfg(phy_backed_up_digital_register_count_is_set)] +type PhyDigRegsBackup = + [u32; esp_metadata_generated::property!("phy.backed_up_digital_register_count")]; + +#[cfg(esp32)] +/// Callback to update the MAC time. +/// +/// The duration is the delta, that has been accumulated between the PHY clock and the normal +/// system timers, since the last time this callback was called. This accounts for the PHY being +/// enabled and disabled, before this callback was set. +pub type MacTimeUpdateCb = fn(Duration); + +static ESP_PHY_LOCK: RawMutex = RawMutex::new(); + +/// PHY initialization state +struct PhyState { + /// Number of references to the PHY. + ref_count: usize, + /// The calibration data used for initialization. + /// + /// If this is [None], when `PhyController::enable_phy` is called, it will be initialized to + /// zero and a full calibration is performed. + calibration_data: Option, + /// Has the PHY been calibrated since the chip was powered up. + calibrated: bool, + + #[cfg(phy_backed_up_digital_register_count_is_set)] + /// Backup of the digital PHY registers. + phy_digital_register_backup: Option, + + // Chip specific. + #[cfg(esp32)] + /// Timestamp at which the modem clock domain state transitioned. + phy_clock_state_transition_timestamp: Instant, + #[cfg(esp32)] + /// The accumulated delta since the last time the callback was called. + mac_clock_delta_since_last_call: Duration, + #[cfg(esp32)] + /// Callback to update the MAC time. + mac_time_update_cb: Option, +} + +impl PhyState { + /// Initialize the PHY state. + pub const fn new() -> Self { + Self { + ref_count: 0, + calibration_data: None, + calibrated: false, + + #[cfg(phy_backed_up_digital_register_count_is_set)] + phy_digital_register_backup: None, + + #[cfg(esp32)] + phy_clock_state_transition_timestamp: Instant::EPOCH, + #[cfg(esp32)] + mac_clock_delta_since_last_call: Duration::ZERO, + #[cfg(esp32)] + mac_time_update_cb: None, + } + } + + /// Get a reference to the calibration data. + /// + /// If no calibration data is available, it will be initialized to zero. + pub fn calibration_data(&mut self) -> &mut PhyCalibrationData { + self.calibration_data + .get_or_insert([0u8; PHY_CALIBRATION_DATA_LENGTH]) + } + + /// Calibrate the PHY. + fn calibrate(&mut self) { + #[cfg(esp32s2)] + unsafe { + use esp_hal::efuse::Efuse; + phy_eco_version_sel(Efuse::major_chip_version()); + } + // Causes headaches for some reason. + // See: https://github.com/esp-rs/esp-hal/issues/4015 + // #[cfg(phy_combo_module)] + // unsafe { + // phy_init_param_set(1); + // } + + #[cfg(all( + phy_enable_usb, + any(soc_has_usb0, soc_has_usb_device), + not(any(esp32s2, esp32h2)) + ))] + unsafe { + unsafe extern "C" { + fn phy_bbpll_en_usb(param: bool); + } + phy_bbpll_en_usb(true); + } + + let calibration_data_available = self.calibration_data.is_some(); + let calibration_mode = if calibration_data_available { + // If the SOC just woke up from deep sleep and + // `phy_skip_calibration_after_deep_sleep` is enabled, no calibration will be + // performed. + cfg_if::cfg_if! { + if #[cfg(phy_skip_calibration_after_deep_sleep)] { + use esp_hal::{rtc_cntl::SocResetReason, system::reset_reason}; + if reset_reason() == Some(SocResetReason::CoreDeepSleep) { + esp_phy_calibration_mode_t_PHY_RF_CAL_NONE + } else { + esp_phy_calibration_mode_t_PHY_RF_CAL_PARTIAL + } + } else { + esp_phy_calibration_mode_t_PHY_RF_CAL_PARTIAL + } + } + } else { + esp_phy_calibration_mode_t_PHY_RF_CAL_FULL + }; + let init_data = &phy_init_data::PHY_INIT_DATA_DEFAULT; + unsafe { + register_chipv7_phy( + init_data, + self.calibration_data() as *mut PhyCalibrationData as *mut _, + calibration_mode, + ); + } + self.calibrated = true; + } + + #[cfg(phy_backed_up_digital_register_count_is_set)] + /// Backup the digital PHY register into memory. + fn backup_digital_regs(&mut self) { + unsafe { + phy_dig_reg_backup( + true, + self.phy_digital_register_backup.get_or_insert_default() as *mut u32, + ); + } + } + + #[cfg(phy_backed_up_digital_register_count_is_set)] + /// Restore the digital PHY registers from memory. + /// + /// This panics if the registers weren't previously backed up. + fn restore_digital_regs(&mut self) { + unsafe { + phy_dig_reg_backup( + false, + self.phy_digital_register_backup + .as_mut() + .expect("Can't restore digital PHY registers from backup, without a backup.") + as *mut u32, + ); + self.phy_digital_register_backup = None; + } + } + + /// Increase the number of references to the PHY. + /// + /// If the ref count was zero, the PHY will be initialized. + pub fn increase_ref_count(&mut self) { + if self.ref_count == 0 { + #[cfg(esp32)] + { + let now = Instant::now(); + let delta = now - self.phy_clock_state_transition_timestamp; + self.phy_clock_state_transition_timestamp = now; + self.mac_clock_delta_since_last_call += delta; + } + if self.calibrated { + unsafe { + phy_wakeup_init(); + } + #[cfg(phy_backed_up_digital_register_count_is_set)] + self.restore_digital_regs(); + } else { + self.calibrate(); + self.calibrated = true; + } + } + #[cfg(esp32)] + if let Some(cb) = self.mac_time_update_cb { + (cb)(self.mac_clock_delta_since_last_call); + self.mac_clock_delta_since_last_call = Duration::ZERO; + } + + self.ref_count += 1; + } + + /// Decrease the number of reference to the PHY. + /// + /// If the ref count hits zero, the PHY will be deinitialized. + /// + /// # Panics + /// This panics, if the PHY ref count is already at zero. + pub fn decrease_ref_count(&mut self) { + self.ref_count = self + .ref_count + .checked_sub(1) + .expect("PHY init ref count dropped below zero."); + if self.ref_count == 0 { + #[cfg(phy_backed_up_digital_register_count_is_set)] + self.backup_digital_regs(); + unsafe { + // Disable PHY and RF. + phy_close_rf(); + + // Power down PHY temperature sensor. + #[cfg(not(esp32))] + phy_xpd_tsens(); + } + #[cfg(esp32)] + { + self.phy_clock_state_transition_timestamp = Instant::now(); + } + // The PHY clock guard will get released in the drop code of the PhyInitGuard. Note + // that this accepts a slight skewing of the delta, since the clock will be disabled + // after we record the value. This shouldn't be too bad though. + } + } +} + +/// Global PHY initialization state +static PHY_STATE: NonReentrantMutex = NonReentrantMutex::new(PhyState::new()); + +#[derive(Debug)] +/// Prevents the PHY from being deinitialized. +/// +/// As long as at least one [PhyInitGuard] exists, the PHY will remain initialized. To release this +/// guard, you can either let it go out of scope, or use [PhyInitGuard::release] to explicitly +/// release it. +pub struct PhyInitGuard<'d> { + _phy_clock_guard: PhyClockGuard<'d>, +} + +impl PhyInitGuard<'_> { + #[inline] + /// Release the init guard. + /// + /// The PHY will be disabled, if this is the last init guard. + pub fn release(self) {} +} + +impl Drop for PhyInitGuard<'_> { + fn drop(&mut self) { + PHY_STATE.with(|phy_state| phy_state.decrease_ref_count()); + } +} + +/// Common functionality for controlling PHY initialization. +pub trait PhyController<'d>: private::Sealed + ModemClockController<'d> { + fn enable_phy(&self) -> PhyInitGuard<'d> { + // In esp-idf, this is done after calculating the MAC time delta, but it shouldn't make + // much of a difference. + let _phy_clock_guard = self.enable_phy_clock(); + + PHY_STATE.with(|phy_state| phy_state.increase_ref_count()); + + PhyInitGuard { _phy_clock_guard } + } + + /// Decreases the PHY init reference count for this modem ignoring + /// currently alive [PhyInitGuard]s. + /// + /// This will also decrease the PHY clock ref count. + /// # Panics + /// This function panics if the PHY is inactive. If the ref count is + /// lower than the number of alive [PhyInitGuard]s, dropping a guard can + /// now panic. + fn decrease_phy_ref_count(&self) { + PHY_STATE.with(|phy_state| phy_state.decrease_ref_count()); + self.decrease_phy_clock_ref_count(); + } +} +macro_rules! impl_phy_controller { + ($feature_gate:ident, $peripheral:tt) => { + #[cfg($feature_gate)] + impl private::Sealed for esp_hal::peripherals::$peripheral<'_> {} + + #[cfg($feature_gate)] + impl<'d> PhyController<'d> for esp_hal::peripherals::$peripheral<'d> {} + }; +} +impl_phy_controller!(wifi, WIFI); +impl_phy_controller!(bt, BT); +impl_phy_controller!(ieee802154, IEEE802154); + +#[cfg(esp32)] +/// Trait providing MAC time functionality for the Wi-Fi peripheral. +pub trait MacTimeExt { + /// Set the MAC time update callback. + /// + /// See [MacTimeUpdateCb] for details. + fn set_mac_time_update_cb(&self, mac_time_update_cb: MacTimeUpdateCb) { + PHY_STATE.with(|phy_state| phy_state.mac_time_update_cb = Some(mac_time_update_cb)); + } +} +#[cfg(esp32)] +impl MacTimeExt for esp_hal::peripherals::WIFI<'_> {} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Calibration data was already set. +pub struct CalibrationDataAlreadySetError; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// No calibration data is available. +pub struct NoCalibrationDataError; + +/// Load previously backed up PHY calibration data. +pub fn set_phy_calibration_data( + calibration_data: &PhyCalibrationData, +) -> Result<(), CalibrationDataAlreadySetError> { + PHY_STATE.with(|phy_state| { + if phy_state.calibration_data.is_some() { + Err(CalibrationDataAlreadySetError) + } else { + phy_state.calibration_data = Some(*calibration_data); + Ok(()) + } + }) +} + +/// Backup the PHY calibration data to the provided slice. +pub fn backup_phy_calibration_data( + buffer: &mut PhyCalibrationData, +) -> Result<(), NoCalibrationDataError> { + PHY_STATE.with(|phy_state| { + phy_state + .calibration_data + .as_mut() + .ok_or(NoCalibrationDataError) + .map(|calibration_data| buffer.copy_from_slice(calibration_data.as_slice())) + }) +} diff --git a/esp-phy/src/phy_init_data/mod.rs b/esp-phy/src/phy_init_data/mod.rs new file mode 100644 index 000000000..8617a19cb --- /dev/null +++ b/esp-phy/src/phy_init_data/mod.rs @@ -0,0 +1,9 @@ +#[cfg_attr(esp32c3, path = "phy_init_data_esp32c3.rs")] +#[cfg_attr(esp32c2, path = "phy_init_data_esp32c2.rs")] +#[cfg_attr(esp32c6, path = "phy_init_data_esp32c6.rs")] +#[cfg_attr(esp32h2, path = "phy_init_data_esp32h2.rs")] +#[cfg_attr(esp32, path = "phy_init_data_esp32.rs")] +#[cfg_attr(esp32s3, path = "phy_init_data_esp32s3.rs")] +#[cfg_attr(esp32s2, path = "phy_init_data_esp32s2.rs")] +mod chip_phy_init_data; +pub(crate) use chip_phy_init_data::PHY_INIT_DATA_DEFAULT; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32.rs similarity index 97% rename from esp-radio/src/common_adapter/phy_init_data_esp32.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32.rs index f051bbaae..b28845b2e 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP32_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32c2.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32c2.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32c2.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32c2.rs index b761fc028..727ca9e6f 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32c2.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32c2.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP32_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32c3.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32c3.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32c3.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32c3.rs index b761fc028..727ca9e6f 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32c3.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32c3.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP32_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32c6.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32c6.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32c6.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32c6.rs index d379b0bec..8582cdfc0 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32c6.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32c6.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32h2.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32h2.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32h2.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32h2.rs index d379b0bec..8582cdfc0 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32h2.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32h2.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32s2.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32s2.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32s2.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32s2.rs index 055929a53..e36304952 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32s2.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32s2.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/src/common_adapter/phy_init_data_esp32s3.rs b/esp-phy/src/phy_init_data/phy_init_data_esp32s3.rs similarity index 98% rename from esp-radio/src/common_adapter/phy_init_data_esp32s3.rs rename to esp-phy/src/phy_init_data/phy_init_data_esp32s3.rs index 71186f37a..673cd6b4c 100644 --- a/esp-radio/src/common_adapter/phy_init_data_esp32s3.rs +++ b/esp-phy/src/phy_init_data/phy_init_data_esp32s3.rs @@ -1,4 +1,4 @@ -use crate::binary::include::esp_phy_init_data_t; +use esp_wifi_sys::include::esp_phy_init_data_t; const CONFIG_ESP_PHY_MAX_TX_POWER: u8 = 20; diff --git a/esp-radio/CHANGELOG.md b/esp-radio/CHANGELOG.md index a32ea68d9..afdf4295b 100644 --- a/esp-radio/CHANGELOG.md +++ b/esp-radio/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AuthMethod`, `Protocol`, `AccessPointInfo`, `AccessPointConfiguration`, `ClientConfiguration`, `Capability`, `Configuration`, `WifiEvent`, `InternalWifiError`, `ScanTypeConfig`, `WifiState`, and `WifiMode` - The `Configuration`, `ClientConfiguration`, `AccessPointConfiguration`, and `EapClientConfiguration` enums have been renamed to `Config`, `ClientConfig`, `AccessPointConfig`, and `EapClientConfig` (#3994) - Error types implements `core::error:Error` +- Use `esp-phy` internally for PHY initialization (#3892) - `ap_state()` and `sta_state()` marked as stable (#4017) - `wifi_state()` marked as unstable (#4017) - `ap_mac` and `sta_mac` returns `[u8; 6]` instead of taking an `[u8; 6]` argument (#4017) diff --git a/esp-radio/Cargo.toml b/esp-radio/Cargo.toml index d82373a0d..8cbb87b0c 100644 --- a/esp-radio/Cargo.toml +++ b/esp-radio/Cargo.toml @@ -57,6 +57,7 @@ esp-alloc = { version = "0.8.0", path = "../esp-alloc", optional = true } esp-config = { version = "0.5.0", path = "../esp-config" } esp-metadata-generated = { version = "0.1.0", path = "../esp-metadata-generated" } esp-sync = { version = "0.0.0", path = "../esp-sync" } +esp-phy = { path = "../esp-phy/" } esp-wifi-sys = { version = "0.8.1" } num-derive = "0.4.2" num-traits = { version = "0.2.19", default-features = false } @@ -91,30 +92,35 @@ default = ["esp-alloc"] # Target the ESP32-C2. esp32c2 = [ "esp-hal/esp32c2", + "esp-phy/esp32c2", "esp-wifi-sys/esp32c2", "esp-metadata-generated/esp32c2", ] # Target the ESP32-C3. esp32c3 = [ "esp-hal/esp32c3", + "esp-phy/esp32c3", "esp-wifi-sys/esp32c3", "esp-metadata-generated/esp32c3", ] # Target the ESP32-C6. esp32c6 = [ "esp-hal/esp32c6", + "esp-phy/esp32c6", "esp-wifi-sys/esp32c6", "esp-metadata-generated/esp32c6", ] # Target the ESP32-H2. esp32h2 = [ "esp-hal/esp32h2", + "esp-phy/esp32h2", "esp-wifi-sys/esp32h2", "esp-metadata-generated/esp32h2", ] # Target the ESP32. esp32 = [ "esp-hal/esp32", + "esp-phy/esp32", "esp-wifi-sys/esp32", "esp-metadata-generated/esp32", "xtensa-lx-rt/float-save-restore", @@ -122,6 +128,7 @@ esp32 = [ # Target the ESP32-S2. esp32s2 = [ "esp-hal/esp32s2", + "esp-phy/esp32s2", "esp-wifi-sys/esp32s2", "esp-metadata-generated/esp32s2", "xtensa-lx-rt/float-save-restore", @@ -129,6 +136,7 @@ esp32s2 = [ # Target the ESP32-S3. esp32s3 = [ "esp-hal/esp32s3", + "esp-phy/esp32s3", "esp-wifi-sys/esp32s3", "esp-metadata-generated/esp32s3", "xtensa-lx-rt/float-save-restore", diff --git a/esp-radio/ld/esp32_provides.x b/esp-radio/ld/esp32_provides.x index a9639f2e0..60d03ac1b 100644 --- a/esp-radio/ld/esp32_provides.x +++ b/esp-radio/ld/esp32_provides.x @@ -13,8 +13,6 @@ EXTERN( __esp_radio_misc_nvs_init ); EXTERN( __esp_radio_misc_nvs_restore ); EXTERN( __ESP_RADIO_G_LOG_LEVEL ); EXTERN( __ESP_RADIO_G_MISC_NVS ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -23,8 +21,6 @@ EXTERN( __esp_radio_fgets ); EXTERN( __esp_radio_fclose ); EXTERN( __esp_radio_sleep ); EXTERN( __esp_radio_usleep ); -EXTERN( __esp_radio_phy_enter_critical ); -EXTERN( __esp_radio_phy_exit_critical ); EXTERN( __esp_radio_esp_timer_get_time ); EXTERN( __esp_radio_esp_event_post ); EXTERN( __esp_radio_vTaskDelay ); @@ -44,8 +40,6 @@ PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init ); PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore ); PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL ); PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); @@ -54,8 +48,6 @@ PROVIDE( fgets = __esp_radio_fgets ); PROVIDE( fclose = __esp_radio_fclose ); PROVIDE( sleep = __esp_radio_sleep ); PROVIDE( usleep = __esp_radio_usleep ); -PROVIDE( phy_enter_critical = __esp_radio_phy_enter_critical ); -PROVIDE( phy_exit_critical = __esp_radio_phy_exit_critical ); PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time ); PROVIDE( esp_event_post = __esp_radio_esp_event_post ); PROVIDE( vTaskDelay = __esp_radio_vTaskDelay ); diff --git a/esp-radio/ld/esp32c2_provides.x b/esp-radio/ld/esp32c2_provides.x index 30fa5f42b..d95ce51af 100644 --- a/esp-radio/ld/esp32c2_provides.x +++ b/esp-radio/ld/esp32c2_provides.x @@ -5,8 +5,6 @@ EXTERN( __ESP_RADIO_WIFI_EVENT ); EXTERN( __esp_radio_gettimeofday ); EXTERN( __esp_radio_esp_fill_random ); EXTERN( __esp_radio_strrchr ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -27,8 +25,6 @@ PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT ); PROVIDE( gettimeofday = __esp_radio_gettimeofday ); PROVIDE( esp_fill_random = __esp_radio_esp_fill_random ); PROVIDE( strrchr = __esp_radio_strrchr ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); diff --git a/esp-radio/ld/esp32c3_provides.x b/esp-radio/ld/esp32c3_provides.x index 89422c25e..c34fe3a6a 100644 --- a/esp-radio/ld/esp32c3_provides.x +++ b/esp-radio/ld/esp32c3_provides.x @@ -5,8 +5,8 @@ EXTERN( __ESP_RADIO_WIFI_EVENT ); EXTERN( __esp_radio_gettimeofday ); EXTERN( __esp_radio_esp_fill_random ); EXTERN( __esp_radio_strrchr ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); + + EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -27,8 +27,8 @@ PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT ); PROVIDE( gettimeofday = __esp_radio_gettimeofday ); PROVIDE( esp_fill_random = __esp_radio_esp_fill_random ); PROVIDE( strrchr = __esp_radio_strrchr ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); + + PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); diff --git a/esp-radio/ld/esp32c6_provides.x b/esp-radio/ld/esp32c6_provides.x index 30fa5f42b..8dcdbd028 100644 --- a/esp-radio/ld/esp32c6_provides.x +++ b/esp-radio/ld/esp32c6_provides.x @@ -5,8 +5,8 @@ EXTERN( __ESP_RADIO_WIFI_EVENT ); EXTERN( __esp_radio_gettimeofday ); EXTERN( __esp_radio_esp_fill_random ); EXTERN( __esp_radio_strrchr ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); + + EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -27,8 +27,8 @@ PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT ); PROVIDE( gettimeofday = __esp_radio_gettimeofday ); PROVIDE( esp_fill_random = __esp_radio_esp_fill_random ); PROVIDE( strrchr = __esp_radio_strrchr ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); + + PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); diff --git a/esp-radio/ld/esp32h2_provides.x b/esp-radio/ld/esp32h2_provides.x index f8b8252bb..5deabea54 100644 --- a/esp-radio/ld/esp32h2_provides.x +++ b/esp-radio/ld/esp32h2_provides.x @@ -8,8 +8,8 @@ EXTERN( __esp_radio_strrchr ); EXTERN( __esp_radio_misc_nvs_deinit ); EXTERN( __esp_radio_misc_nvs_init ); EXTERN( __ESP_RADIO_G_LOG_LEVEL ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); + + EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -31,8 +31,8 @@ PROVIDE( strrchr = __esp_radio_strrchr ); PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit ); PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init ); PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); + + PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); diff --git a/esp-radio/ld/esp32s2_provides.x b/esp-radio/ld/esp32s2_provides.x index 7477ca167..e9ab2a7d4 100644 --- a/esp-radio/ld/esp32s2_provides.x +++ b/esp-radio/ld/esp32s2_provides.x @@ -14,8 +14,8 @@ EXTERN( __esp_radio_misc_nvs_init ); EXTERN( __esp_radio_misc_nvs_restore ); EXTERN( __ESP_RADIO_G_LOG_LEVEL ); EXTERN( __ESP_RADIO_G_MISC_NVS ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); + + EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -24,13 +24,10 @@ EXTERN( __esp_radio_fgets ); EXTERN( __esp_radio_fclose ); EXTERN( __esp_radio_sleep ); EXTERN( __esp_radio_usleep ); -EXTERN( __esp_radio_phy_enter_critical ); -EXTERN( __esp_radio_phy_exit_critical ); + EXTERN( __esp_radio_esp_event_post ); EXTERN( __esp_radio_vTaskDelay ); EXTERN( __esp_radio_puts ); -EXTERN( __esp_radio_sleep ); -EXTERN( __esp_radio_usleep ); PROVIDE( strdup = __esp_radio_strdup ); PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time ); @@ -45,8 +42,8 @@ PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init ); PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore ); PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL ); PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); + + PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); @@ -55,10 +52,7 @@ PROVIDE( fgets = __esp_radio_fgets ); PROVIDE( fclose = __esp_radio_fclose ); PROVIDE( sleep = __esp_radio_sleep ); PROVIDE( usleep = __esp_radio_usleep ); -PROVIDE( phy_enter_critical = __esp_radio_phy_enter_critical ); -PROVIDE( phy_exit_critical = __esp_radio_phy_exit_critical ); + PROVIDE( esp_event_post = __esp_radio_esp_event_post ); PROVIDE( vTaskDelay = __esp_radio_vTaskDelay ); PROVIDE( puts = __esp_radio_puts ); -PROVIDE( sleep = __esp_radio_sleep ); -PROVIDE( usleep = __esp_radio_usleep ); diff --git a/esp-radio/ld/esp32s3_provides.x b/esp-radio/ld/esp32s3_provides.x index 4253ecc26..c1889ab8e 100644 --- a/esp-radio/ld/esp32s3_provides.x +++ b/esp-radio/ld/esp32s3_provides.x @@ -13,8 +13,8 @@ EXTERN( __esp_radio_misc_nvs_init ); EXTERN( __esp_radio_misc_nvs_restore ); EXTERN( __ESP_RADIO_G_LOG_LEVEL ); EXTERN( __ESP_RADIO_G_MISC_NVS ); -EXTERN( __esp_radio_esp_dport_access_reg_read ); -EXTERN( __esp_radio_rtc_get_xtal ); + + EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_putchar ); EXTERN( __esp_radio_fwrite ); @@ -30,6 +30,10 @@ EXTERN( __esp_radio_puts ); EXTERN( __esp_radio_sleep ); EXTERN( __esp_radio_usleep ); +/* If this isn't included, linking fails on the S3.*/ +EXTERN( bt_bb_v2_init_cmplx ); + + PROVIDE( strdup = __esp_radio_strdup ); PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS ); PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS ); @@ -42,8 +46,8 @@ PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init ); PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore ); PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL ); PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS ); -PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read ); -PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal ); + + PROVIDE( putchar = __esp_radio_putchar ); PROVIDE( _putchar = __esp_radio_putchar ); PROVIDE( fwrite = __esp_radio_fwrite ); diff --git a/esp-radio/src/ble/btdm.rs b/esp-radio/src/ble/btdm.rs index cbb6036b2..717a34cb7 100644 --- a/esp-radio/src/ble/btdm.rs +++ b/esp-radio/src/ble/btdm.rs @@ -1,6 +1,7 @@ use alloc::boxed::Box; use core::ptr::{addr_of, addr_of_mut}; +use esp_phy::{PhyController, PhyInitGuard}; use esp_sync::RawMutex; use esp_wifi_sys::c_types::*; use portable_atomic::{AtomicBool, Ordering}; @@ -53,6 +54,9 @@ unsafe extern "C" { fn API_vhci_host_check_send_available() -> bool; fn API_vhci_host_send_packet(data: *const u8, len: u16); fn API_vhci_host_register_callback(vhci_host_callbac: *const VhciHostCallbacks) -> i32; + + #[cfg(not(esp32))] + fn coex_pti_v2(); } static VHCI_HOST_CALLBACK: VhciHostCallbacks = VhciHostCallbacks { @@ -299,7 +303,8 @@ unsafe extern "C" fn custom_queue_create( todo!(); } -pub(crate) fn ble_init() { +pub(crate) fn ble_init() -> PhyInitGuard<'static> { + let phy_init_guard; unsafe { (*addr_of_mut!(HCI_OUT_COLLECTOR)).write(HciOutCollector::new()); // turn on logging @@ -352,16 +357,19 @@ pub(crate) fn ble_init() { #[cfg(coex)] crate::binary::include::coex_enable(); - crate::common_adapter::phy_enable(); + phy_init_guard = esp_hal::peripherals::BT::steal().enable_phy(); - #[cfg(esp32)] - { - unsafe extern "C" { - fn btdm_rf_bb_init_phase2(); + cfg_if::cfg_if! { + if #[cfg(esp32)] { + unsafe extern "C" { + fn btdm_rf_bb_init_phase2(); + } + + btdm_rf_bb_init_phase2(); + coex_bt_high_prio(); + } else { + coex_pti_v2(); } - - btdm_rf_bb_init_phase2(); - coex_bt_high_prio(); } #[cfg(coex)] @@ -374,6 +382,7 @@ pub(crate) fn ble_init() { // At some point the "High-speed ADC" entropy source became available. unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() }; + phy_init_guard } pub(crate) fn ble_deinit() { @@ -387,8 +396,8 @@ pub(crate) fn ble_deinit() { unsafe { btdm_controller_deinit(); - crate::common_adapter::phy_disable(); } + // Disabling the PHY happens automatically, when the BLEController gets dropped. } /// Sends HCI data to the BLE controller. #[instability::unstable] diff --git a/esp-radio/src/ble/controller/mod.rs b/esp-radio/src/ble/controller/mod.rs index 50992b526..2048f0e4b 100644 --- a/esp-radio/src/ble/controller/mod.rs +++ b/esp-radio/src/ble/controller/mod.rs @@ -1,4 +1,5 @@ use embedded_io::{Error, ErrorType, Read, Write}; +use esp_phy::PhyInitGuard; use super::{read_hci, read_next, send_hci}; use crate::Controller; @@ -6,15 +7,14 @@ use crate::Controller; /// A blocking HCI connector #[instability::unstable] pub struct BleConnector<'d> { + _phy_init_guard: PhyInitGuard<'d>, _device: crate::hal::peripherals::BT<'d>, } - impl Drop for BleConnector<'_> { fn drop(&mut self) { crate::ble::ble_deinit(); } } - impl<'d> BleConnector<'d> { /// Create and init a new BLE connector. #[instability::unstable] @@ -22,9 +22,10 @@ impl<'d> BleConnector<'d> { _init: &'d Controller<'d>, device: crate::hal::peripherals::BT<'d>, ) -> BleConnector<'d> { - crate::ble::ble_init(); - - Self { _device: device } + Self { + _phy_init_guard: crate::ble::ble_init(), + _device: device, + } } /// Read the next HCI packet from the BLE controller. diff --git a/esp-radio/src/ble/npl.rs b/esp-radio/src/ble/npl.rs index dd7fab1ac..b03043787 100644 --- a/esp-radio/src/ble/npl.rs +++ b/esp-radio/src/ble/npl.rs @@ -5,6 +5,7 @@ use core::{ }; use esp_hal::time::Instant; +use esp_phy::{PhyController, PhyInitGuard}; use super::*; use crate::{ @@ -270,6 +271,8 @@ unsafe extern "C" { pub(crate) fn r_ble_hci_trans_buf_alloc(typ: i32) -> *const u8; pub(crate) fn r_ble_hci_trans_buf_free(buf: *const u8); + + pub(crate) fn coex_pti_v2(); } #[repr(C)] @@ -1050,7 +1053,8 @@ pub(crate) struct BleNplCountInfoT { mutex_count: u16, } -pub(crate) fn ble_init() { +pub(crate) fn ble_init() -> PhyInitGuard<'static> { + let phy_init_guard; unsafe { (*addr_of_mut!(HCI_OUT_COLLECTOR)).write(HciOutCollector::new()); @@ -1145,11 +1149,13 @@ pub(crate) fn ble_init() { os_msys_init(); } - crate::common_adapter::phy_enable(); + phy_init_guard = esp_hal::peripherals::BT::steal().enable_phy(); // init bb bt_bb_v2_init_cmplx(1); + coex_pti_v2(); + #[cfg(coex)] { let rc = ble_osi_coex_funcs_register(&G_COEX_FUNCS as *const OsiCoexFuncsT); @@ -1250,6 +1256,7 @@ pub(crate) fn ble_init() { unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() }; debug!("The ble_controller_init was initialized"); + phy_init_guard } pub(crate) fn ble_deinit() { @@ -1299,8 +1306,6 @@ pub(crate) fn ble_deinit() { npl::esp_unregister_npl_funcs(); npl::esp_unregister_ext_funcs(); - - crate::common_adapter::phy_disable(); } } diff --git a/esp-radio/src/common_adapter/mod.rs b/esp-radio/src/common_adapter.rs similarity index 79% rename from esp-radio/src/common_adapter/mod.rs rename to esp-radio/src/common_adapter.rs index ce137f0b5..f36b2a81c 100644 --- a/esp-radio/src/common_adapter/mod.rs +++ b/esp-radio/src/common_adapter.rs @@ -1,17 +1,9 @@ #![allow(dead_code)] -use esp_sync::NonReentrantMutex; use esp_wifi_sys::{ c_types::c_char, - include::{ - esp_phy_calibration_data_t, - esp_phy_calibration_mode_t, - get_phy_version_str, - register_chipv7_phy, - timeval, - }, + include::{esp_phy_calibration_data_t, timeval}, }; -use portable_atomic::{AtomicU32, Ordering}; use crate::{ binary::{ @@ -23,49 +15,6 @@ use crate::{ time::blob_ticks_to_micros, }; -#[cfg_attr(esp32c3, path = "common_adapter_esp32c3.rs")] -#[cfg_attr(esp32c2, path = "common_adapter_esp32c2.rs")] -#[cfg_attr(esp32c6, path = "common_adapter_esp32c6.rs")] -#[cfg_attr(esp32h2, path = "common_adapter_esp32h2.rs")] -#[cfg_attr(esp32, path = "common_adapter_esp32.rs")] -#[cfg_attr(esp32s3, path = "common_adapter_esp32s3.rs")] -#[cfg_attr(esp32s2, path = "common_adapter_esp32s2.rs")] -pub(crate) mod chip_specific; - -#[cfg_attr(esp32c3, path = "phy_init_data_esp32c3.rs")] -#[cfg_attr(esp32c2, path = "phy_init_data_esp32c2.rs")] -#[cfg_attr(esp32c6, path = "phy_init_data_esp32c6.rs")] -#[cfg_attr(esp32h2, path = "phy_init_data_esp32h2.rs")] -#[cfg_attr(esp32, path = "phy_init_data_esp32.rs")] -#[cfg_attr(esp32s3, path = "phy_init_data_esp32s3.rs")] -#[cfg_attr(esp32s2, path = "phy_init_data_esp32s2.rs")] -pub(crate) mod phy_init_data; - -static PHY_ACCESS_REF: NonReentrantMutex = NonReentrantMutex::new(0); - -pub(crate) unsafe fn phy_enable() { - PHY_ACCESS_REF.with(|ref_count| { - *ref_count += 1; - if *ref_count == 1 { - unsafe { chip_specific::phy_enable_inner() }; - } - }) -} - -#[allow(unused)] -pub(crate) unsafe fn phy_disable() { - PHY_ACCESS_REF.with(|ref_count| { - *ref_count -= 1; - if *ref_count == 0 { - unsafe { chip_specific::phy_disable_inner() }; - } - }) -} - -static CAL_DATA: esp_sync::NonReentrantMutex< - [u8; core::mem::size_of::()], -> = esp_sync::NonReentrantMutex::new([0u8; core::mem::size_of::()]); - /// ************************************************************************** /// Name: esp_semphr_create /// @@ -341,7 +290,33 @@ pub unsafe extern "C" fn __esp_radio_strrchr(_s: *const (), _c: u32) -> *const u todo!("strrchr"); } -static PHY_CLOCK_ENABLE_REF: AtomicU32 = AtomicU32::new(0); +#[unsafe(no_mangle)] +static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0; + +#[unsafe(no_mangle)] +pub static mut __ESP_RADIO_G_MISC_NVS: *mut u32 = &raw mut NVS as *mut u32; + +pub static mut NVS: [u32; 15] = [0u32; 15]; + +// For some reason these are only necessary on Xtensa chips. +#[cfg(xtensa)] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_radio_misc_nvs_deinit() { + trace!("misc_nvs_deinit") +} + +#[cfg(xtensa)] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 { + trace!("misc_nvs_init"); + 0 +} + +#[cfg(xtensa)] +#[unsafe(no_mangle)] +unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 { + todo!("misc_nvs_restore") +} // We're use either WIFI or BT here, since esp-radio also supports the ESP32-H2 as the only // chip, with BT but without WIFI. @@ -350,66 +325,73 @@ type ModemClockControllerPeripheral = esp_hal::peripherals::WIFI<'static>; #[cfg(esp32h2)] type ModemClockControllerPeripheral = esp_hal::peripherals::BT<'static>; +#[allow(unused)] pub(crate) unsafe fn phy_enable_clock() { - let count = PHY_CLOCK_ENABLE_REF.fetch_add(1, Ordering::Acquire); - if count == 0 { - // Stealing the peripheral is safe here, as they must have been passed into the relevant - // initialization functions for the Wi-Fi or BLE controller, if this code gets executed. - let clock_guard = unsafe { ModemClockControllerPeripheral::steal() }.enable_phy_clock(); - core::mem::forget(clock_guard); - - trace!("phy_enable_clock done!"); - } + // Stealing the peripheral is safe here, as they must have been passed into the relevant + // initialization functions for the Wi-Fi or BLE controller, if this code gets executed. + let clock_guard = unsafe { ModemClockControllerPeripheral::steal() }.enable_phy_clock(); + core::mem::forget(clock_guard); } #[allow(unused)] pub(crate) unsafe fn phy_disable_clock() { - let count = PHY_CLOCK_ENABLE_REF.fetch_sub(1, Ordering::Release); - if count == 1 { - unsafe { ModemClockControllerPeripheral::steal() }.decrease_phy_clock_ref_count(); - trace!("phy_disable_clock done!"); - } + unsafe { ModemClockControllerPeripheral::steal() }.decrease_phy_clock_ref_count(); } - -pub(crate) fn phy_calibrate() { - let phy_version = unsafe { get_phy_version_str() }; - trace!("phy_version {}", unsafe { str_from_c(phy_version) }); - - let init_data = &phy_init_data::PHY_INIT_DATA_DEFAULT; - - unsafe { - chip_specific::bbpll_en_usb(); - } - - #[cfg(phy_full_calibration)] - const CALIBRATION_MODE: esp_phy_calibration_mode_t = - esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_FULL; - #[cfg(not(phy_full_calibration))] - const CALIBRATION_MODE: esp_phy_calibration_mode_t = - esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_PARTIAL; - - #[cfg(phy_skip_calibration_after_deep_sleep)] - let calibration_mode = if crate::hal::system::reset_reason() - == Some(crate::hal::rtc_cntl::SocResetReason::CoreDeepSleep) +pub(crate) fn enable_wifi_power_domain() { + #[cfg(not(any(soc_has_pmu, esp32c2)))] { - esp_wifi_sys::include::esp_phy_calibration_mode_t_PHY_RF_CAL_NONE - } else { - CALIBRATION_MODE - }; - #[cfg(not(phy_skip_calibration_after_deep_sleep))] - let calibration_mode = CALIBRATION_MODE; + cfg_if::cfg_if! { + if #[cfg(soc_has_lpwr)] { + let rtc_cntl = esp_hal::peripherals::LPWR::regs(); + } else { + let rtc_cntl = esp_hal::peripherals::RTC_CNTL::regs(); + } + } - debug!("Using calibration mode {}", calibration_mode); + rtc_cntl + .dig_pwc() + .modify(|_, w| w.wifi_force_pd().clear_bit()); - let res = CAL_DATA.with(|cal_data| unsafe { - register_chipv7_phy( - init_data, - cal_data as *mut _ as *mut crate::binary::include::esp_phy_calibration_data_t, - calibration_mode, - ) - }); + #[cfg(not(esp32))] + unsafe { + cfg_if::cfg_if! { + if #[cfg(soc_has_apb_ctrl)] { + let syscon = esp_hal::peripherals::APB_CTRL::regs(); + } else { + let syscon = esp_hal::peripherals::SYSCON::regs(); + } + } + const WIFIBB_RST: u32 = 1 << 0; // Wi-Fi baseband + const FE_RST: u32 = 1 << 1; // RF Frontend RST + const WIFIMAC_RST: u32 = 1 << 2; // Wi-Fi MAC - debug!("register_chipv7_phy result = {}", res); + const BTBB_RST: u32 = 1 << 3; // Bluetooth Baseband + const BTMAC_RST: u32 = 1 << 4; // deprecated + const RW_BTMAC_RST: u32 = 1 << 9; // Bluetooth MAC + const RW_BTMAC_REG_RST: u32 = 1 << 11; // Bluetooth MAC Regsiters + const BTBB_REG_RST: u32 = 1 << 13; // Bluetooth Baseband Registers + + const MODEM_RESET_FIELD_WHEN_PU: u32 = WIFIBB_RST + | FE_RST + | WIFIMAC_RST + | if cfg!(soc_has_bt) { + BTBB_RST | BTMAC_RST | RW_BTMAC_RST | RW_BTMAC_REG_RST | BTBB_RST + } else { + 0 + }; + + syscon + .wifi_rst_en() + .modify(|r, w| w.bits(r.bits() | MODEM_RESET_FIELD_WHEN_PU)); + syscon + .wifi_rst_en() + .modify(|r, w| w.bits(r.bits() & !MODEM_RESET_FIELD_WHEN_PU)); + } + + rtc_cntl + .dig_iso() + .modify(|_, w| w.wifi_force_iso().clear_bit()); + } } /// Get calibration data. @@ -418,17 +400,19 @@ pub(crate) fn phy_calibrate() { /// /// If you see the data is different than what was persisted before, consider persisting the new /// data. -pub fn phy_calibration_data() -> [u8; core::mem::size_of::()] { - CAL_DATA.with(|cal_data| *cal_data) +pub fn phy_calibration_data(data: &mut [u8; esp_phy::PHY_CALIBRATION_DATA_LENGTH]) { + // Although we're ignoring the result here, this doesn't change the behavior, as this just + // doesn't do anything in case an error is returned. + let _ = esp_phy::backup_phy_calibration_data(data); } /// Set calibration data. /// /// This will be used next time the phy gets initialized. pub fn set_phy_calibration_data(data: &[u8; core::mem::size_of::()]) { - CAL_DATA.with(|cal_data| { - *cal_data = *data; - }); + // Although we're ignoring the result here, this doesn't change the behavior, as this just + // doesn't do anything in case an error is returned. + let _ = esp_phy::set_phy_calibration_data(data); } /// ************************************************************************** diff --git a/esp-radio/src/common_adapter/common_adapter_esp32.rs b/esp-radio/src/common_adapter/common_adapter_esp32.rs deleted file mode 100644 index 952d08961..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32.rs +++ /dev/null @@ -1,195 +0,0 @@ -use crate::{ - binary::include::*, - hal::{peripherals::LPWR, ram}, -}; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - LPWR::regs() - .dig_pwc() - .modify(|_, w| w.wifi_force_pd().clear_bit()); - - LPWR::regs() - .dig_iso() - .modify(|_, w| w.wifi_force_iso().clear_bit()); -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - // nothing for ESP32 -} - -pub(super) unsafe fn phy_enable_inner() { - // #if CONFIG_IDF_TARGET_ESP32 - // // Update time stamp - // s_phy_rf_en_ts = esp_timer_get_time(); - // // Update WiFi MAC time before WiFi/BT common clock is enabled - // phy_update_wifi_mac_time(false, s_phy_rf_en_ts); - // #endif - - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(coex)] - unsafe { - coex_bt_high_prio(); - } - - trace!("PHY ENABLE"); -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // #if CONFIG_IDF_TARGET_ESP32 - // // Update WiFi MAC time before disalbe WiFi/BT common peripheral - // clock phy_update_wifi_mac_time(true, - // esp_timer_get_time()); #endif - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} - -/// ************************************************************************** -/// Name: esp_dport_access_reg_read -/// -/// Description: -/// Read regitser value safely in SMP -/// -/// Input Parameters: -/// reg - Register address -/// -/// Returned Value: -/// Register value -/// -/// ************************************************************************* -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_esp_dport_access_reg_read(reg: u32) -> u32 { - unsafe { - // trace!("esp_dport_access_reg_read {:x} => {:x}", reg, res); - (reg as *mut u32).read_volatile() - } -} - -/// ************************************************************************** -/// Name: phy_enter_critical -/// -/// Description: -/// Enter critical state -/// -/// Input Parameters: -/// None -/// -/// Returned Value: -/// CPU PS value -/// -/// ************************************************************************* -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_phy_enter_critical() -> u32 { - trace!("phy_enter_critical"); - - unsafe { crate::ESP_RADIO_LOCK.acquire().inner() } -} - -/// ************************************************************************** -/// Name: phy_exit_critical -/// -/// Description: -/// Exit from critical state -/// -/// Input Parameters: -/// level - CPU PS value -/// -/// Returned Value: -/// None -/// -/// ************************************************************************* -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_phy_exit_critical(level: u32) { - trace!("phy_exit_critical {}", level); - - unsafe { - let token = esp_sync::RestoreState::new(level); - crate::ESP_RADIO_LOCK.release(token); - } -} - -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_rtc_get_xtal() -> u32 { - use esp_hal::clock::Clock; - - let xtal = crate::hal::clock::RtcClock::xtal_freq(); - xtal.mhz() -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_deinit() { - trace!("misc_nvs_deinit") -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 { - trace!("misc_nvs_init"); - 0 -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 { - todo!("misc_nvs_restore") -} - -#[unsafe(no_mangle)] -static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0; - -#[unsafe(no_mangle)] -pub static mut __ESP_RADIO_G_MISC_NVS: u32 = 0; diff --git a/esp-radio/src/common_adapter/common_adapter_esp32c2.rs b/esp-radio/src/common_adapter/common_adapter_esp32c2.rs deleted file mode 100644 index 78f054cad..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32c2.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::binary::include::*; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - // In esp-idf, neither SOC_PM_SUPPORT_MODEM_PD or SOC_PM_SUPPORT_WIFI_PD are - // defined, which makes `esp_wifi_bt_power_domain_on` a no-op. -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - // nothing for ESP32-C2 -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - unsafe extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } - - trace!("PHY ENABLE"); -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // #if CONFIG_IDF_TARGET_ESP32 - // // Update WiFi MAC time before disalbe WiFi/BT common peripheral - // clock phy_update_wifi_mac_time(true, - // esp_timer_get_time()); #endif - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} diff --git a/esp-radio/src/common_adapter/common_adapter_esp32c3.rs b/esp-radio/src/common_adapter/common_adapter_esp32c3.rs deleted file mode 100644 index 022c666cb..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32c3.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::{ - binary::include::*, - hal::peripherals::{APB_CTRL, LPWR}, -}; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - const SYSTEM_WIFIBB_RST: u32 = 1 << 0; - const SYSTEM_FE_RST: u32 = 1 << 1; - const SYSTEM_WIFIMAC_RST: u32 = 1 << 2; - const SYSTEM_BTBB_RST: u32 = 1 << 3; // Bluetooth Baseband - const SYSTEM_BTMAC_RST: u32 = 1 << 4; // deprecated - const SYSTEM_RW_BTMAC_RST: u32 = 1 << 9; // Bluetooth MAC - const SYSTEM_RW_BTMAC_REG_RST: u32 = 1 << 11; // Bluetooth MAC Regsiters - const SYSTEM_BTBB_REG_RST: u32 = 1 << 13; // Bluetooth Baseband Registers - - const MODEM_RESET_FIELD_WHEN_PU: u32 = SYSTEM_WIFIBB_RST - | SYSTEM_FE_RST - | SYSTEM_WIFIMAC_RST - | SYSTEM_BTBB_RST - | SYSTEM_BTMAC_RST - | SYSTEM_RW_BTMAC_RST - | SYSTEM_RW_BTMAC_REG_RST - | SYSTEM_BTBB_REG_RST; - - LPWR::regs() - .dig_pwc() - .modify(|_, w| w.wifi_force_pd().clear_bit()); - - APB_CTRL::regs() - .wifi_rst_en() - .modify(|r, w| unsafe { w.bits(r.bits() | MODEM_RESET_FIELD_WHEN_PU) }); - - APB_CTRL::regs() - .wifi_rst_en() - .modify(|r, w| unsafe { w.bits(r.bits() & !MODEM_RESET_FIELD_WHEN_PU) }); - - LPWR::regs() - .dig_iso() - .modify(|_, w| w.wifi_force_iso().clear_bit()); -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - #[cfg(phy_enable_usb)] - { - unsafe extern "C" { - fn phy_bbpll_en_usb(param: bool); - } - - unsafe { - phy_bbpll_en_usb(true); - } - } -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - unsafe extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } - - trace!("PHY ENABLE"); -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // #if CONFIG_IDF_TARGET_ESP32 - // // Update WiFi MAC time before disalbe WiFi/BT common peripheral - // clock phy_update_wifi_mac_time(true, - // esp_timer_get_time()); #endif - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} diff --git a/esp-radio/src/common_adapter/common_adapter_esp32c6.rs b/esp-radio/src/common_adapter/common_adapter_esp32c6.rs deleted file mode 100644 index fd39def85..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32c6.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::binary::include::*; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - // In esp-idf, SOC_PMU_SUPPORTED is set which makes - // `esp_wifi_bt_power_domain_on` a no-op. -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - #[cfg(phy_enable_usb)] - { - unsafe extern "C" { - fn phy_bbpll_en_usb(param: bool); - } - - unsafe { - phy_bbpll_en_usb(true); - } - } -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - unsafe extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } - - trace!("PHY ENABLE"); -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // #if CONFIG_IDF_TARGET_ESP32 - // // Update WiFi MAC time before disable WiFi/BT common peripheral - // clock phy_update_wifi_mac_time(true, - // esp_timer_get_time()); #endif - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} diff --git a/esp-radio/src/common_adapter/common_adapter_esp32h2.rs b/esp-radio/src/common_adapter/common_adapter_esp32h2.rs deleted file mode 100644 index 987d6c2d1..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32h2.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::binary::include::*; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - // In esp-idf, SOC_PMU_SUPPORTED is set which makes - // `esp_wifi_bt_power_domain_on` a no-op. -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - // nothing for ESP32-H2 -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - unsafe extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } - - trace!("PHY ENABLE"); -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // #if CONFIG_IDF_TARGET_ESP32 - // // Update WiFi MAC time before disalbe WiFi/BT common peripheral - // clock phy_update_wifi_mac_time(true, - // esp_timer_get_time()); #endif - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} diff --git a/esp-radio/src/common_adapter/common_adapter_esp32s2.rs b/esp-radio/src/common_adapter/common_adapter_esp32s2.rs deleted file mode 100644 index 3c1ad8446..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32s2.rs +++ /dev/null @@ -1,184 +0,0 @@ -use crate::{ - binary::include::*, - hal::{ - peripherals::{LPWR, SYSCON}, - ram, - }, -}; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn enable_wifi_power_domain() { - const DPORT_WIFIBB_RST: u32 = 1 << 0; - const DPORT_FE_RST: u32 = 1 << 1; - const DPORT_WIFIMAC_RST: u32 = 1 << 2; - const DPORT_BTBB_RST: u32 = 1 << 3; - const DPORT_BTMAC_RST: u32 = 1 << 4; - const DPORT_RW_BTMAC_RST: u32 = 1 << 9; - - const MODEM_RESET_FIELD_WHEN_PU: u32 = DPORT_WIFIBB_RST - | DPORT_FE_RST - | DPORT_WIFIMAC_RST - | DPORT_BTBB_RST - | DPORT_BTMAC_RST - | DPORT_RW_BTMAC_RST; - - LPWR::regs() - .dig_pwc() - .modify(|_, w| w.wifi_force_pd().clear_bit()); - - SYSCON::regs() - .wifi_rst_en() - .modify(|r, w| unsafe { w.bits(r.bits() | MODEM_RESET_FIELD_WHEN_PU) }); - - SYSCON::regs() - .wifi_rst_en() - .modify(|r, w| unsafe { w.bits(r.bits() & !MODEM_RESET_FIELD_WHEN_PU) }); - - LPWR::regs() - .dig_iso() - .modify(|_, w| w.wifi_force_iso().clear_bit()); -} - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - // nothing for ESP32-S2 -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } -} - -#[allow(unused)] -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} - -/// ************************************************************************** -/// Name: phy_enter_critical -/// -/// Description: -/// Enter critical state -/// -/// Input Parameters: -/// None -/// -/// Returned Value: -/// CPU PS value -/// -/// ************************************************************************* -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_phy_enter_critical() -> u32 { - trace!("phy_enter_critical"); - - unsafe { crate::ESP_RADIO_LOCK.acquire().inner() } -} - -/// ************************************************************************** -/// Name: phy_exit_critical -/// -/// Description: -/// Exit from critical state -/// -/// Input Parameters: -/// level - CPU PS value -/// -/// Returned Value: -/// None -/// -/// ************************************************************************* -#[ram] -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_phy_exit_critical(level: u32) { - trace!("phy_exit_critical {}", level); - - unsafe { - let token = esp_sync::RestoreState::new(level); - crate::ESP_RADIO_LOCK.release(token); - } -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_deinit() { - trace!("misc_nvs_deinit") -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 { - trace!("misc_nvs_init"); - 0 -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 { - todo!("misc_nvs_restore") -} - -#[unsafe(no_mangle)] -static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0; - -#[unsafe(no_mangle)] -pub static mut __ESP_RADIO_G_MISC_NVS: &u32 = unsafe { &*core::ptr::addr_of!(NVS) }; - -pub static mut NVS: u32 = 0; diff --git a/esp-radio/src/common_adapter/common_adapter_esp32s3.rs b/esp-radio/src/common_adapter/common_adapter_esp32s3.rs deleted file mode 100644 index 2a5c8dde3..000000000 --- a/esp-radio/src/common_adapter/common_adapter_esp32s3.rs +++ /dev/null @@ -1,151 +0,0 @@ -use crate::binary::include::*; - -const SOC_PHY_DIG_REGS_MEM_SIZE: usize = 21 * 4; - -static mut SOC_PHY_DIG_REGS_MEM: [u8; SOC_PHY_DIG_REGS_MEM_SIZE] = [0u8; SOC_PHY_DIG_REGS_MEM_SIZE]; -static mut G_IS_PHY_CALIBRATED: bool = false; -static mut G_PHY_DIGITAL_REGS_MEM: *mut u32 = core::ptr::null_mut(); -static mut S_IS_PHY_REG_STORED: bool = false; - -pub(crate) fn phy_mem_init() { - unsafe { - G_PHY_DIGITAL_REGS_MEM = core::ptr::addr_of_mut!(SOC_PHY_DIG_REGS_MEM).cast(); - } -} - -pub(crate) fn enable_wifi_power_domain() { - const SYSTEM_WIFIBB_RST: u32 = 1 << 0; - const SYSTEM_FE_RST: u32 = 1 << 1; - const SYSTEM_WIFIMAC_RST: u32 = 1 << 2; - const SYSTEM_BTBB_RST: u32 = 1 << 3; // Bluetooth Baseband - const SYSTEM_BTMAC_RST: u32 = 1 << 4; // deprecated - const SYSTEM_RW_BTMAC_RST: u32 = 1 << 9; // Bluetooth MAC - const SYSTEM_RW_BTMAC_REG_RST: u32 = 1 << 11; // Bluetooth MAC Regsiters - const SYSTEM_BTBB_REG_RST: u32 = 1 << 13; // Bluetooth Baseband Registers - - const MODEM_RESET_FIELD_WHEN_PU: u32 = SYSTEM_WIFIBB_RST - | SYSTEM_FE_RST - | SYSTEM_WIFIMAC_RST - | SYSTEM_BTBB_RST - | SYSTEM_BTMAC_RST - | SYSTEM_RW_BTMAC_RST - | SYSTEM_RW_BTMAC_REG_RST - | SYSTEM_BTBB_REG_RST; - - unsafe { - let rtc_cntl = &*crate::hal::peripherals::LPWR::ptr(); - let syscon = &*crate::hal::peripherals::APB_CTRL::ptr(); - - rtc_cntl - .dig_pwc() - .modify(|_, w| w.wifi_force_pd().clear_bit()); - - syscon - .wifi_rst_en() - .modify(|r, w| w.bits(r.bits() | MODEM_RESET_FIELD_WHEN_PU)); - syscon - .wifi_rst_en() - .modify(|r, w| w.bits(r.bits() & !MODEM_RESET_FIELD_WHEN_PU)); - - rtc_cntl - .dig_iso() - .modify(|_, w| w.wifi_force_iso().clear_bit()); - } -} - -pub(crate) unsafe fn bbpll_en_usb() { - #[cfg(phy_enable_usb)] - { - unsafe extern "C" { - fn phy_bbpll_en_usb(param: bool); - } - - unsafe { - phy_bbpll_en_usb(true); - } - } -} - -pub(super) unsafe fn phy_enable_inner() { - unsafe { - super::phy_enable_clock(); - } - - if unsafe { !G_IS_PHY_CALIBRATED } { - super::phy_calibrate(); - unsafe { G_IS_PHY_CALIBRATED = true }; - } else { - unsafe { - phy_wakeup_init(); - } - phy_digital_regs_load(); - } - - #[cfg(feature = "ble")] - { - unsafe extern "C" { - fn coex_pti_v2(); - } - unsafe { - coex_pti_v2(); - } - } - - trace!("PHY ENABLE"); -} - -pub(super) unsafe fn phy_disable_inner() { - phy_digital_regs_store(); - unsafe { - // Disable PHY and RF. - phy_close_rf(); - - // Disable PHY temperature sensor - phy_xpd_tsens(); - - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware - // RNG - super::phy_disable_clock(); - } - - trace!("PHY DISABLE"); -} - -fn phy_digital_regs_load() { - unsafe { - if S_IS_PHY_REG_STORED && !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(false, G_PHY_DIGITAL_REGS_MEM); - } - } -} - -fn phy_digital_regs_store() { - unsafe { - if !G_PHY_DIGITAL_REGS_MEM.is_null() { - phy_dig_reg_backup(true, G_PHY_DIGITAL_REGS_MEM); - S_IS_PHY_REG_STORED = true; - } - } -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_deinit() { - trace!("misc_nvs_deinit") -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 { - trace!("misc_nvs_init"); - 0 -} - -#[unsafe(no_mangle)] -unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 { - todo!("misc_nvs_restore") -} - -#[unsafe(no_mangle)] -static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0; - -#[unsafe(no_mangle)] -pub static mut __ESP_RADIO_G_MISC_NVS: u32 = 0; diff --git a/esp-radio/src/ieee802154/mod.rs b/esp-radio/src/ieee802154/mod.rs index db5e5edbb..d25973bb3 100644 --- a/esp-radio/src/ieee802154/mod.rs +++ b/esp-radio/src/ieee802154/mod.rs @@ -17,6 +17,7 @@ use byte::{BytesExt, TryRead}; use esp_hal::{clock::PhyClockGuard, peripherals::IEEE802154}; +use esp_phy::PhyInitGuard; use esp_sync::NonReentrantMutex; use ieee802154::mac::{self, FooterMode, FrameSerDesContext}; @@ -111,6 +112,7 @@ pub struct Ieee802154<'a> { _align: u32, transmit_buffer: [u8; FRAME_SIZE], _phy_clock_guard: PhyClockGuard<'a>, + _phy_init_guard: PhyInitGuard<'a>, } impl<'a> Ieee802154<'a> { @@ -119,10 +121,12 @@ impl<'a> Ieee802154<'a> { /// NOTE: Coexistence with Wi-Fi or Bluetooth is currently not possible. If you do it anyway, /// things will break. pub fn new(radio: IEEE802154<'a>) -> Self { + let (_phy_clock_guard, _phy_init_guard) = esp_ieee802154_enable(radio); Self { _align: 0, transmit_buffer: [0u8; FRAME_SIZE], - _phy_clock_guard: esp_ieee802154_enable(radio), + _phy_clock_guard, + _phy_init_guard, } } diff --git a/esp-radio/src/ieee802154/raw.rs b/esp-radio/src/ieee802154/raw.rs index 81e394383..ccf211512 100644 --- a/esp-radio/src/ieee802154/raw.rs +++ b/esp-radio/src/ieee802154/raw.rs @@ -6,6 +6,7 @@ use esp_hal::{ interrupt::Priority, peripherals::IEEE802154, }; +use esp_phy::{PhyController, PhyInitGuard}; use esp_sync::NonReentrantMutex; use esp_wifi_sys::include::{ ieee802154_coex_event_t, @@ -80,19 +81,20 @@ pub struct RawReceived { pub channel: u8, } -pub(crate) fn esp_ieee802154_enable(mut radio: IEEE802154<'_>) -> PhyClockGuard<'_> { +pub(crate) fn esp_ieee802154_enable( + mut radio: IEEE802154<'_>, +) -> (PhyClockGuard<'_>, PhyInitGuard<'_>) { init_radio_clocks(); let phy_clock_guard = radio.enable_phy_clock(); radio.enable_modem_clock(true); - unsafe { - crate::common_adapter::phy_enable(); - } + let phy_init_guard = radio.enable_phy(); + esp_btbb_enable(); ieee802154_mac_init(); info!("date={:x}", mac_date()); - phy_clock_guard + (phy_clock_guard, phy_init_guard) } fn esp_btbb_enable() { diff --git a/esp-radio/src/lib.rs b/esp-radio/src/lib.rs index b9c620726..23fcfcee3 100644 --- a/esp-radio/src/lib.rs +++ b/esp-radio/src/lib.rs @@ -55,7 +55,7 @@ //! Please note that the configuration keys are usually named slightly different and not all configuration keys apply. #![cfg_attr( feature = "wifi", - doc = "By default the power-saving mode is [PowerSaveMode::None](crate::wifi::PowerSaveMode::None) and `ESP_RADIO_PHY_ENABLE_USB` is enabled by default." + doc = "By default the power-saving mode is [PowerSaveMode::None](crate::wifi::PowerSaveMode::None) and `ESP_PHY_PHY_ENABLE_USB` is enabled by default." )] //! In addition pay attention to these configuration keys: //! - `ESP_RADIO_RX_QUEUE_SIZE` @@ -129,7 +129,6 @@ mod fmt; use core::marker::PhantomData; -use common_adapter::chip_specific::phy_mem_init; pub use common_adapter::{phy_calibration_data, set_phy_calibration_data}; use esp_hal::{self as hal}; use esp_radio_preempt_driver as preempt; @@ -295,8 +294,7 @@ pub fn init<'d>() -> Result, InitializationError> { return Err(InitializationError::WrongClockConfig); } - crate::common_adapter::chip_specific::enable_wifi_power_domain(); - phy_mem_init(); + crate::common_adapter::enable_wifi_power_domain(); setup_radio_isr(); diff --git a/esp-radio/src/wifi/mod.rs b/esp-radio/src/wifi/mod.rs index 2498b7b2a..571dfcfef 100644 --- a/esp-radio/src/wifi/mod.rs +++ b/esp-radio/src/wifi/mod.rs @@ -1370,7 +1370,20 @@ pub fn sta_mac() -> [u8; 6] { mac } -pub(crate) fn wifi_init() -> Result<(), WifiError> { +#[cfg(esp32)] +fn set_mac_time_update_cb(wifi: crate::hal::peripherals::WIFI<'_>) { + use esp_phy::MacTimeExt; + use esp_wifi_sys::include::esp_wifi_internal_update_mac_time; + unsafe { + wifi.set_mac_time_update_cb(|duration| { + esp_wifi_internal_update_mac_time(duration.as_micros() as u32); + }); + } +} + +pub(crate) fn wifi_init(_wifi: crate::hal::peripherals::WIFI<'_>) -> Result<(), WifiError> { + #[cfg(esp32)] + set_mac_time_update_cb(_wifi); unsafe { #[cfg(coex)] esp_wifi_result!(coex_init())?; @@ -1393,12 +1406,6 @@ pub(crate) fn wifi_init() -> Result<(), WifiError> { Some(recv_cb_ap) ))?; - #[cfg(any(esp32, esp32s3))] - { - static mut NVS_STRUCT: [u32; 12] = [0; 12]; - chip_specific::__ESP_RADIO_G_MISC_NVS = addr_of!(NVS_STRUCT) as u32; - } - Ok(()) } } @@ -2951,7 +2958,7 @@ impl WifiConfig { /// currently in use. pub fn new<'d>( _inited: &'d Controller<'d>, - _device: crate::hal::peripherals::WIFI<'d>, + device: crate::hal::peripherals::WIFI<'d>, config: WifiConfig, ) -> Result<(WifiController<'d>, Interfaces<'d>), WifiError> { if crate::is_interrupts_disabled() { @@ -2998,7 +3005,7 @@ pub fn new<'d>( TX_QUEUE_SIZE.store(config.tx_queue_size, Ordering::Relaxed); }; - crate::wifi::wifi_init()?; + crate::wifi::wifi_init(device)?; unsafe { let country = config.country_code.into_blob(); diff --git a/esp-radio/src/wifi/os_adapter/mod.rs b/esp-radio/src/wifi/os_adapter/mod.rs index 83e54598a..4053b3368 100644 --- a/esp-radio/src/wifi/os_adapter/mod.rs +++ b/esp-radio/src/wifi/os_adapter/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod os_adapter_chip_specific; use allocator_api2::boxed::Box; use enumset::EnumSet; +use esp_phy::PhyController; use esp_sync::{NonReentrantMutex, RawMutex}; use super::WifiEvent; @@ -778,8 +779,7 @@ pub unsafe extern "C" fn wifi_apb80m_release() { /// ************************************************************************* pub unsafe extern "C" fn phy_disable() { trace!("phy_disable"); - - unsafe { crate::common_adapter::phy_disable() } + unsafe { WIFI::steal() }.decrease_phy_ref_count(); } /// ************************************************************************** @@ -798,8 +798,7 @@ pub unsafe extern "C" fn phy_disable() { pub unsafe extern "C" fn phy_enable() { // quite some code needed here trace!("phy_enable"); - - unsafe { crate::common_adapter::phy_enable() } + core::mem::forget(unsafe { WIFI::steal() }.enable_phy()); } /// ************************************************************************** diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 35041aaf1..d51ae2df9 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -57,6 +57,7 @@ pub enum Package { EspLpHal, EspMetadata, EspMetadataGenerated, + EspPhy, EspPrintln, EspRiscvRt, EspStorage, @@ -177,6 +178,7 @@ impl Package { EspHal | EspLpHal | EspRadio + | EspPhy | EspHalEmbassy | EspRomSys | EspBootloaderEspIdf