Split out PHY init into esp-phy crate. (#3892)

* Minimal infrastructure

* Implemented dig reg backup.

* usb bbpll

* Removed default feature.

* OS adapter tweaks

* Fixed S2 and implemented PhyController

* Added manual deinit.

* Fixed linker scripts and migrated esp-radio to esp-phy

* Fixed warnings.

* Fixed NPL

* Tried fixing NPL again

* Fixed ieee802154

* Fixed reading chip version of S3.

* fmt

* Added changelog entry

* Added changelog for esp-radio

* Deleted chip specific common adapters.

* Added docs and unstable

* Migrated cal data load/store to esp-phy

* Fixed PHY cal CI error

* Removed instability

* Removed feature from esp-phy

* fmt

* Fixed esp-sync docs.

* Removed log with CONFIG

* Removed nonreentrantmutex from common adapter

* Disable reset for radio blocks where required.

* Fixed cfg_if for s2

* fmt

* Added bt_bb_v2_init_cmplx to phy_provides.x

* Added CHANGELOG

* Moved EXTERN and fixed comment.

* Fixed lint

* Fixed common adapter again.

* Docs and Readme.

* Fixed ref count.

* This time pls.

* Added MAC time update CB for esp-radio

* fixed field init

* Fixed inconsistency in metadata

* Removed useless changelog entry

* Fixed S2.

* Swaped addr_of for &raw mut

* Properly initialize NVS

* Fixed lint

* Fixed C6

* Fixed remaining issues

* Fixed CI

* Added link

* Updated esp-wifi-sys in esp-phy

* Address reviews

* Renamed PHY lock

* Moved syscon let in common_adapter

* Fmt

* Remove critical_section

* Don't steal when not necessary

* Added esp-phy changelog to workflow

* Add cargo metadata for esp-phy

* Added reference to #4015

* Refixed Cargo.toml

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
This commit is contained in:
Simon Neuenhausen 2025-09-19 16:14:25 +02:00 committed by GitHub
parent 83105b4dbb
commit 8e29b925cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
67 changed files with 1308 additions and 1141 deletions

View File

@ -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

View File

@ -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/
docs\.espressif\.com/projects/rust/esp-sync/latest/

View File

@ -13,6 +13,7 @@ exclude = [
"esp-lp-hal",
"esp-metadata",
"esp-metadata-generated",
"esp-phy",
"esp-println",
"esp-preempt",
"esp-radio-preempt-driver",

View File

@ -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, Sha<N>Context`: Work-queue based SHA driver (#4013)
- I2S: `i2s::master::Config` with support for more TDM mode standards (#3985)

View File

@ -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

View File

@ -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);

View File

@ -15,6 +15,25 @@ impl super::Efuse {
pub fn rwdt_multiplier() -> u8 {
Self::read_field_le::<u8>(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::<u8>(WAFER_VERSION_MINOR_HI) << 3
| Self::read_field_le::<u8>(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)]

View File

@ -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::<u8>(WAFER_VERSION_MINOR_HI) << 3
| Self::read_field_le::<u8>(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)]

View File

@ -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 {

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -677,3 +677,5 @@ apb_cycle_wait_num = 16 # TODO
## Radio
[device.wifi]
[device.bt]
[device.phy]
combo_module = true

View File

@ -306,3 +306,5 @@ apb_cycle_wait_num = 16 # TODO
## Radio
[device.wifi]
[device.bt]
[device.phy]
combo_module = true

View File

@ -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

View File

@ -544,3 +544,5 @@ apb_cycle_wait_num = 16 # TODO
## Radio
[device.bt]
[device.ieee802154]
[device.phy]
combo_module = true

View File

@ -451,3 +451,4 @@ apb_cycle_wait_num = 16 # TODO
## Radio
[device.bt]
[device.ieee802154]
[device.phy]

View File

@ -505,3 +505,4 @@ apb_cycle_wait_num = 16 # TODO
## Radio
[device.wifi]
[device.phy]

View File

@ -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

View File

@ -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<u32>,
}
},
];

12
esp-phy/CHANGELOG.md Normal file
View File

@ -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)

90
esp-phy/Cargo.toml Normal file
View File

@ -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",
]

29
esp-phy/README.md Normal file
View File

@ -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.

29
esp-phy/build.rs Normal file
View File

@ -0,0 +1,29 @@
use std::error::Error as StdError;
use esp_config::generate_config_from_yaml_definition;
fn main() -> Result<(), Box<dyn StdError>> {
// 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(())
}

19
esp-phy/esp_config.yml Normal file
View File

@ -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

9
esp-phy/phy_provides.x Normal file
View File

@ -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 );

View File

@ -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()
}

312
esp-phy/src/fmt.rs Normal file
View File

@ -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<Self::Ok, Self::Error>;
}
impl<T> Try for Option<T> {
type Ok = T;
type Error = NoneError;
#[inline]
fn into_result(self) -> Result<T, NoneError> {
self.ok_or(NoneError)
}
}
impl<T, E> Try for Result<T, E> {
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)
}
}

373
esp-phy/src/lib.rs Normal file
View File

@ -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::<esp_wifi_sys::include::esp_phy_calibration_data_t>();
/// 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<PhyCalibrationData>,
/// 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<PhyDigRegsBackup>,
// 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<MacTimeUpdateCb>,
}
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<PhyState> = 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()))
})
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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",

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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 );

View File

@ -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]

View File

@ -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.

View File

@ -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();
}
}

View File

@ -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<usize> = 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_phy_calibration_data_t>()],
> = esp_sync::NonReentrantMutex::new([0u8; core::mem::size_of::<esp_phy_calibration_data_t>()]);
/// **************************************************************************
/// 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::<esp_phy_calibration_data_t>()] {
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::<esp_phy_calibration_data_t>()]) {
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);
}
/// **************************************************************************

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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,
}
}

View File

@ -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() {

View File

@ -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<Controller<'d>, 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();

View File

@ -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();

View File

@ -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());
}
/// **************************************************************************

View File

@ -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