Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion esp-hal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a

| Driver | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ------------- |:-----:|:--------:|:--------:|:--------:|:--------:|:---------:|:--------:|:--------:|:--------:|:--------:|:---------:|
| Bluetooth | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | ⚒️ | |
| Bluetooth | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | ⚒️ | ⚒️ |
| WIFI | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | ⚒️ | ⚒️ | ⚒️ |
| IEEE 802.15.4 | | | | ⚒️ | ⚒️ | | ⚒️ | | | | ⚒️ |
| Ethernet | ⚒️ | | | | | | | ⚒️ | | | ⚒️ |
Expand Down
25 changes: 25 additions & 0 deletions esp-hal/src/soc/esp32/clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ impl CpuClock {
syscon_pre_div: None,
cpu_clk: Some(CpuClkConfig::Pll),
rtc_slow_clk: Some(xtal32k::default_rtc_slow_clk()),
// The divisor follows the detected crystal. `configure` fills it in.
ble_lp_clk: None,
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
timg_calibration_clock: None,
};
Expand All @@ -70,6 +72,8 @@ impl CpuClock {
syscon_pre_div: None,
cpu_clk: Some(CpuClkConfig::Pll),
rtc_slow_clk: Some(xtal32k::default_rtc_slow_clk()),
// The divisor follows the detected crystal. `configure` fills it in.
ble_lp_clk: None,
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
timg_calibration_clock: None,
};
Expand All @@ -81,6 +85,8 @@ impl CpuClock {
syscon_pre_div: None,
cpu_clk: Some(CpuClkConfig::Pll),
rtc_slow_clk: Some(xtal32k::default_rtc_slow_clk()),
// The divisor follows the detected crystal. `configure` fills it in.
ble_lp_clk: None,
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
timg_calibration_clock: None,
};
Expand Down Expand Up @@ -129,6 +135,15 @@ impl ClockConfig {
self.xtal_clk = Some(xtal);
}

if self.ble_lp_clk.is_none() {
// The controller runs the crystal at 500 kHz.
let xtal_hz = unwrap!(self.xtal_clk).value();
self.ble_lp_clk = Some(BleLpClkConfig::new(
BleLpClkSclk::Xtal,
xtal_hz / 500_000 - 1,
));
}

self.apply(clocks);
}
}
Expand Down Expand Up @@ -772,3 +787,13 @@ impl RmtInstance {
}
}
}

fn enable_ble_lp_clk_impl(_clocks: &mut ClockTree, _en: bool) {}

fn configure_ble_lp_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<BleLpClkConfig>,
_new_config: BleLpClkConfig,
) {
// The BTDM controller programs this mux from the clock-tree selection.
}
50 changes: 49 additions & 1 deletion esp-hal/src/soc/esp32c2/clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use esp_rom_sys::rom::{ets_delay_us, ets_update_cpu_frequency_rom};

use crate::{
clock::RtcClock,
peripherals::{I2C_ANA_MST, LPWR, SYSTEM, TIMG0},
peripherals::{I2C_ANA_MST, LPWR, MODEM_CLKRST, SYSTEM, TIMG0},
rtc_cntl::Rtc,
soc::regi2c,
time::Rate,
Expand Down Expand Up @@ -52,6 +52,8 @@ impl CpuClock {
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
// The divisor follows the detected crystal. `configure` fills it in.
ble_lp_clk: None,
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
Expand All @@ -63,6 +65,8 @@ impl CpuClock {
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
// The divisor follows the detected crystal. `configure` fills it in.
ble_lp_clk: None,
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
Expand Down Expand Up @@ -111,6 +115,21 @@ impl ClockConfig {
self.xtal_clk = Some(xtal);
}

if self.ble_lp_clk.is_none() {
let xtal_hz = unwrap!(self.xtal_clk).value();
// 26 MHz crystals run the timer at 40 kHz. 40 MHz crystals run it at 32 kHz.
// BLE_LP_XTAL_CLK already divides the crystal by 5.
let target_hz = if xtal_hz == 26_000_000 {
40_000
} else {
32_000
};
self.ble_lp_clk = Some(BleLpClkConfig::new(
BleLpClkSclk::Xtal,
xtal_hz / (5 * target_hz) - 1,
));
}

self.apply(clocks);
}
}
Expand Down Expand Up @@ -663,3 +682,32 @@ impl TimgInstance {
});
}
}

fn enable_ble_lp_xtal_clk_impl(_clocks: &mut ClockTree, _en: bool) {
// The divide-by-5 crystal input has no clock gate.
}

fn enable_ble_lp_clk_impl(_clocks: &mut ClockTree, _en: bool) {}

fn configure_ble_lp_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<BleLpClkConfig>,
new_config: BleLpClkConfig,
) {
let sclk = new_config.sclk();

MODEM_CLKRST::regs()
.modem_lp_timer_conf()
.modify(|_, w| unsafe {
w.lp_timer_sel_xtal32k().bit(sclk == BleLpClkSclk::OscSlow);
w.lp_timer_sel_xtal().bit(sclk == BleLpClkSclk::Xtal);
w.lp_timer_sel_8m().clear_bit();
w.lp_timer_sel_rtc_slow().bit(sclk == BleLpClkSclk::RcSlow);
w.lp_timer_clk_div_num().bits(new_config.divisor() as u8)
});

MODEM_CLKRST::regs().etm_clk_conf().modify(|_, w| {
w.etm_clk_active().set_bit();
w.etm_clk_sel().clear_bit()
});
}
20 changes: 20 additions & 0 deletions esp-hal/src/soc/esp32c3/clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ impl CpuClock {
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
// 40 MHz crystal divided to 1 MHz.
ble_lp_clk: Some(BleLpClkConfig::new(
BleLpClkSclk::Xtal,
40_000_000 / 1_000_000 - 1,
)),
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
Expand All @@ -64,6 +69,11 @@ impl CpuClock {
cpu_clk: Some(CpuClkConfig::Pll),
rc_fast_clk_div_n: Some(RcFastClkDivNConfig::new(0)),
rtc_slow_clk: Some(RtcSlowClkConfig::RcSlow),
// 40 MHz crystal divided to 1 MHz.
ble_lp_clk: Some(BleLpClkConfig::new(
BleLpClkSclk::Xtal,
40_000_000 / 1_000_000 - 1,
)),
rtc_fast_clk: Some(RtcFastClkConfig::Rc),
low_power_clk: Some(LowPowerClkConfig::RtcSlow),
timg_calibration_clock: None,
Expand Down Expand Up @@ -678,3 +688,13 @@ impl TimgInstance {
});
}
}

fn enable_ble_lp_clk_impl(_clocks: &mut ClockTree, _en: bool) {}

fn configure_ble_lp_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<BleLpClkConfig>,
_new_config: BleLpClkConfig,
) {
// The BTDM controller programs this mux from the clock-tree selection.
}
67 changes: 66 additions & 1 deletion esp-hal/src/soc/esp32c5/clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// TODO: This is a temporary place for this, should probably be moved into clocks_ll.

use crate::{
peripherals::{I2C_ANA_MST, LP_CLKRST, PCR, PMU},
peripherals::{I2C_ANA_MST, LP_CLKRST, MODEM_LPCON, PCR, PMU},
soc::{regi2c, xtal32k},
};

Expand Down Expand Up @@ -51,6 +51,8 @@ impl CpuClock {
apb_clk: Some(ApbClkConfig::new(0)),
lp_fast_clk: Some(LpFastClkConfig::RcFast),
lp_slow_clk: Some(xtal32k::default_lp_slow_clk()),
// The divisor follows the crystal frequency. `configure` fills it in.
ble_lp_clk: None,
crypto_clk: Some(CryptoClkConfig::PllF480m),
iomux_function_clock: Some(IomuxFunctionClockConfig::PllF80m),
timg_calibration_clock: None,
Expand All @@ -63,6 +65,8 @@ impl CpuClock {
apb_clk: Some(ApbClkConfig::new(0)),
lp_fast_clk: Some(LpFastClkConfig::RcFast),
lp_slow_clk: Some(xtal32k::default_lp_slow_clk()),
// The divisor follows the crystal frequency. `configure` fills it in.
ble_lp_clk: None,
crypto_clk: Some(CryptoClkConfig::PllF480m),
iomux_function_clock: Some(IomuxFunctionClockConfig::PllF80m),
timg_calibration_clock: None,
Expand All @@ -75,6 +79,8 @@ impl CpuClock {
apb_clk: Some(ApbClkConfig::new(0)),
lp_fast_clk: Some(LpFastClkConfig::RcFast),
lp_slow_clk: Some(xtal32k::default_lp_slow_clk()),
// The divisor follows the crystal frequency. `configure` fills it in.
ble_lp_clk: None,
crypto_clk: Some(CryptoClkConfig::PllF480m),
iomux_function_clock: Some(IomuxFunctionClockConfig::PllF80m),
timg_calibration_clock: None,
Expand Down Expand Up @@ -116,6 +122,15 @@ impl ClockConfig {
Some(XtalClkConfig::_48)
};

if self.ble_lp_clk.is_none() {
// The controller runs the crystal at 100 kHz.
let xtal_hz = unwrap!(self.xtal_clk).value();
self.ble_lp_clk = Some(BleLpClkConfig::new(
BleLpClkSclk::Xtal,
xtal_hz / 100_000 - 1,
));
}

self.apply(clocks);
}
}
Expand Down Expand Up @@ -236,6 +251,12 @@ fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, en: bool) {

// OSC_SLOW_CLK

fn enable_rc32k_clk_impl(_clocks: &mut ClockTree, en: bool) {
PMU::regs()
.hp_sleep_lp_ck_power()
.modify(|_, w| w.hp_sleep_xpd_rc32k().bit(en));
}

fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, en: bool) {
LP_CLKRST::regs()
.clk_to_hp()
Expand Down Expand Up @@ -674,3 +695,47 @@ impl TimgInstance {
});
}
}

fn enable_ble_lp_clk_impl(_clocks: &mut ClockTree, en: bool) {
MODEM_LPCON::regs()
.clk_conf()
.modify(|_, w| w.clk_lp_timer_en().bit(en));
}

fn configure_ble_lp_clk_impl(
_clocks: &mut ClockTree,
_old_config: Option<BleLpClkConfig>,
new_config: BleLpClkConfig,
) {
let sclk = new_config.sclk();
let sel_32k = ble_lp_clk_32k_sel(sclk);

MODEM_LPCON::regs()
.test_conf()
.modify(|_, w| w.clk_en().set_bit());

MODEM_LPCON::regs().lp_timer_conf().modify(|_, w| unsafe {
w.clk_lp_timer_sel_osc_slow()
.bit(sclk == BleLpClkSclk::RcSlow);
w.clk_lp_timer_sel_osc_fast().clear_bit();
w.clk_lp_timer_sel_xtal().bit(sclk == BleLpClkSclk::Xtal);
w.clk_lp_timer_sel_xtal32k().bit(sel_32k.is_some());
w.clk_lp_timer_div_num().bits(new_config.divisor() as u16)
});

if let Some(sel) = sel_32k {
MODEM_LPCON::regs()
.modem_32k_clk_conf()
.modify(|_, w| unsafe { w.clk_modem_32k_sel().bits(sel) });
}
}

fn ble_lp_clk_32k_sel(sclk: BleLpClkSclk) -> Option<u8> {
match sclk {
#[cfg(use_xtal32k)]
BleLpClkSclk::Xtal32k => Some(0),
BleLpClkSclk::Rc32k => Some(1),
BleLpClkSclk::Ext32k => Some(2),
_ => None,
}
}
Loading
Loading