Skip to content

Commit

Permalink
Port esp-idf sleep code
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 29, 2023
1 parent 169bb96 commit 8f4a59f
Show file tree
Hide file tree
Showing 9 changed files with 1,177 additions and 43 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,21 @@ jobs:

# Check all RISC-V targets:
- name: check (esp32c3)
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32c3
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32c3 --target=riscv32imc-unknown-none-elf
- name: check (esp32c6)
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32c6
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32c6 --target=riscv32imac-unknown-none-elf
- name: check (esp32h2)
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32h2
run: cd esp-hal-smartled/ && cargo +nightly check --features=esp32h2 --target=riscv32imac-unknown-none-elf
# Check all Xtensa targets:
- name: check (esp32)
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32,xtal-40mhz
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32,xtal-40mhz --target=xtensa-esp32-none-elf
- name: check (esp32s2)
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32s2
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32s2 --target=xtensa-esp32s2-none-elf
- name: check (esp32s3)
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32s3
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32s3 --target=xtensa-esp32s3-none-elf
# Ensure documentation can be built (requires a chip feature!)
- name: rustdoc
run: cd esp-hal-smartled/ && cargo doc --features=esp32c3,esp-hal-common/eh1
run: cd esp-hal-smartled/ && cargo doc --features=esp32c3,esp-hal-common/eh1 --target=riscv32imac-unknown-none-elf

esp32-hal:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added Rx Timeout functionality to async Uart (#911)
- RISC-V: Thread-mode and interrupt-mode executors, `#[main]` macro (#947)
- ESP32-C6: Properly initialize PMU (#974)
- ESP32-C6: Implement light/deep sleep (#918)

### Changed

Expand Down
70 changes: 68 additions & 2 deletions esp-hal-common/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ pub enum RtcFunction {
pub trait RTCPin: Pin {
#[cfg(xtensa)]
fn rtc_number(&self) -> u8;
#[cfg(xtensa)]
#[cfg(any(xtensa, esp32c6))]
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: RtcFunction);

fn rtcio_pad_hold(&mut self, enable: bool);

// Unsafe because `level` needs to be a valid setting for the
// rtc_cntl.gpio_wakeup.gpio_pinX_int_type
#[cfg(esp32c3)]
#[cfg(any(esp32c3, esp32c6))]
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8);
}

Expand Down Expand Up @@ -2528,6 +2528,72 @@ pub mod lp_gpio {
}
}
}

impl<MODE> crate::gpio::RTCPin for GpioPin<MODE, $gpionum> {
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) {
let lp_io = &*crate::peripherals::LP_IO::ptr();
lp_io.[< pin $gpionum >].modify(|_, w| {
w
.[< lp_gpio $gpionum _wakeup_enable >]().bit(wakeup)
.[< lp_gpio $gpionum _int_type >]().bits(level)
});
}

fn rtcio_pad_hold(&mut self, enable: bool) {
let mask = 1 << $gpionum;
unsafe {
let lp_aon = &*crate::peripherals::LP_AON::ptr();

lp_aon.gpio_hold0.modify(|r, w| {
if enable {
w.gpio_hold0().bits(r.gpio_hold0().bits() | mask)
} else {
w.gpio_hold0().bits(r.gpio_hold0().bits() & !mask)
}
});
}
}

/// Set the LP properties of the pin. If `mux` is true then then pin is
/// routed to LP_IO, when false it is routed to IO_MUX.
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: crate::gpio::RtcFunction) {
let mask = 1 << $gpionum;
unsafe {
// Select LP_IO
let lp_aon = &*crate::peripherals::LP_AON::ptr();
lp_aon
.gpio_mux
.modify(|r, w| {
if mux {
w.sel().bits(r.sel().bits() | mask)
} else {
w.sel().bits(r.sel().bits() & !mask)
}
});

// Configure input, function and select normal operation registers
let lp_io = &*crate::peripherals::LP_IO::ptr();
lp_io.[< gpio $gpionum >].modify(|_, w| {
w
.[< lp_gpio $gpionum _slp_sel >]().bit(false)
.[< lp_gpio $gpionum _fun_ie >]().bit(input_enable)
.[< lp_gpio $gpionum _mcu_sel >]().bits(func as u8)
});
}
}
}

impl<MODE> crate::gpio::RTCPinWithResistors for GpioPin<MODE, $gpionum> {
fn rtcio_pullup(&mut self, enable: bool) {
let lp_io = unsafe { &*crate::peripherals::LP_IO::ptr() };
lp_io.[< gpio $gpionum >].modify(|_, w| w.[< lp_gpio $gpionum _fun_wpu >]().bit(enable));
}

fn rtcio_pulldown(&mut self, enable: bool) {
let lp_io = unsafe { &*crate::peripherals::LP_IO::ptr() };
lp_io.[< gpio $gpionum >].modify(|_, w| w.[< lp_gpio $gpionum _fun_wpd >]().bit(enable));
}
}
)+
}
}
Expand Down
12 changes: 6 additions & 6 deletions esp-hal-common/src/rtc_cntl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use crate::efuse::Efuse;
use crate::peripherals::{LP_TIMER, LP_WDT};
#[cfg(not(any(esp32c6, esp32h2)))]
use crate::peripherals::{RTC_CNTL, TIMG0};
#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
use crate::rtc_cntl::sleep::{RtcSleepConfig, WakeSource, WakeTriggers};
use crate::{
clock::Clock,
Expand All @@ -92,7 +92,7 @@ use crate::{
Cpu,
};
// only include sleep where its been implemented
#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub mod sleep;

#[cfg(any(esp32c6, esp32h2))]
Expand Down Expand Up @@ -212,7 +212,7 @@ impl<'d> Rtc<'d> {
swd: Swd::new(),
};

#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
RtcSleepConfig::base_settings(&this);

this
Expand Down Expand Up @@ -272,7 +272,7 @@ impl<'d> Rtc<'d> {
}

/// enter deep sleep and wake with the provided `wake_sources`
#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep_deep<'a>(
&mut self,
wake_sources: &[&'a dyn WakeSource],
Expand All @@ -284,7 +284,7 @@ impl<'d> Rtc<'d> {
}

/// enter light sleep and wake with the provided `wake_sources`
#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep_light<'a>(
&mut self,
wake_sources: &[&'a dyn WakeSource],
Expand All @@ -296,7 +296,7 @@ impl<'d> Rtc<'d> {

/// enter sleep with the provided `config` and wake with the provided
/// `wake_sources`
#[cfg(any(esp32, esp32s3, esp32c3))]
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep<'a>(
&mut self,
config: &RtcSleepConfig,
Expand Down
36 changes: 35 additions & 1 deletion esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,16 @@ bitfield::bitfield! {
pub bool, xpd_xtal , set_xpd_xtal : 31;
}

#[derive(Clone, Copy, Default)]
// pmu_sleep_power_config_t.1
pub struct LpSysPower {
// This is a best-guess assignment of the variants in the union `pmu_lp_power_t` union
// In esp-idf, all three fields are `pmu_lp_power_t`
pub dig_power: LpDigPower,
pub clk_power: LpClkPower,
pub xtal: LpXtalPower,
}

bitfield::bitfield! {
#[derive(Clone, Copy, Default)]
// pmu_lp_analog_t.0
Expand Down Expand Up @@ -1475,7 +1485,7 @@ impl RtcClock {
/// Calibration of RTC_SLOW_CLK is performed using a special feature of
/// TIMG0. This feature counts the number of XTAL clock cycles within a
/// given number of RTC_SLOW_CLK cycles.
fn calibrate_internal(mut cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
pub(crate) fn calibrate_internal(mut cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000;
const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000;
const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768;
Expand Down Expand Up @@ -1790,3 +1800,27 @@ impl RtcClock {
(100_000_000 * 1000 / period) as u16
}
}

pub(crate) fn rtc_clk_cpu_freq_set_xtal() {
let freq_mhz = RtcClock::get_xtal_freq();

unsafe {
// clk_ll_ahb_set_ls_divider(1);
pcr()
.ahb_freq_conf
.modify(|_, w| w.ahb_ls_div_num().bits(0));

// clk_ll_cpu_set_ls_divider(1);
pcr()
.cpu_freq_conf
.modify(|_, w| w.cpu_ls_div_num().bits(0));

// clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
pcr().sysclk_conf.modify(|_, w| w.soc_clk_sel().bits(0));
}

let esp_rom_set_cpu_ticks_per_us: fn(u32) = unsafe { core::mem::transmute(0x4000_0048) };
esp_rom_set_cpu_ticks_per_us(freq_mhz.mhz());

// TODO: don't turn off the bbpll if some consumers depend on bbpll
}
4 changes: 2 additions & 2 deletions esp-hal-common/src/rtc_cntl/sleep/esp32c3.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{TimerWakeupSource, WakeSource, WakeTriggers, WakeupLevel};
use crate::{
gpio::RTCPinWithResistors,
gpio::{RTCPinWithResistors, RtcFunction},
regi2c_write_mask,
rtc_cntl::{sleep::RtcioWakeupSource, Clock, RtcClock},
Rtc,
Expand Down Expand Up @@ -170,7 +170,7 @@ fn isolate_digital_gpio() {
io_mux.gpio[pin_num].modify(|_, w| w.fun_wpd().clear_bit());

// make pad work as gpio (otherwise, deep_sleep bottom current will rise)
io_mux.gpio[pin_num].modify(|_, w| w.mcu_sel().variant(PIN_FUNC_GPIO));
io_mux.gpio[pin_num].modify(|_, w| w.mcu_sel().variant(RtcFunction::Digital as u8));
}
}
}
Expand Down
Loading

0 comments on commit 8f4a59f

Please sign in to comment.