diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36faa940ff1..177048d990e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,8 @@ jobs: run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp32c3 - name: check (esp32c6) run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp32c6 + #- name: check (esp32h2) + # run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp3h2 # Check all Xtensa targets: - name: check (esp32) run: cd esp-hal-smartled/ && cargo +esp check --features=esp32,esp32_40mhz @@ -180,6 +182,39 @@ jobs: - name: check esp32c6-hal (async, spi) run: cd esp32c6-hal/ && cargo +nightly-2023-03-09 check --example=embassy_spi --features=embassy,embassy-time-systick,async + esp32h2-hal: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@v1 + with: + target: riscv32imac-unknown-none-elf + toolchain: nightly-2023-03-09 + components: rust-src + - uses: Swatinem/rust-cache@v2 + + # Perform a full build initially to verify that the examples not only + # build, but also link successfully. + # We also use this as an opportunity to verify that the examples link + # for each supported image format. + - name: build esp32h2-hal (no features) + run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 build --examples + - name: build esp32h2-hal (direct-boot) + run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 build --examples --features=direct-boot + # Subsequent steps can just check the examples instead, as we're already + # confident that they link. + - name: check esp32h2-hal (common features) + run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --examples --features=eh1,ufmt + # - name: check esp32h2-hal (async, systick) + # run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_hello_world --features=embassy,embassy-time-systick + # - name: check esp32h2-hal (async, timg0) + # run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_hello_world --features=embassy,embassy-time-timg0 + # - name: check esp32h2-hal (async, gpio) + # run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_wait --features=embassy,embassy-time-systick,async + # - name: check esp32h2-hal (async, spi) + # run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_spi --features=embassy,embassy-time-systick,async + esp32s2-hal: runs-on: ubuntu-latest @@ -264,6 +299,8 @@ jobs: run: cd esp32c3-hal/ && cargo check --features=eh1,ufmt - name: msrv (esp32c6-hal) run: cd esp32c6-hal/ && cargo check --features=eh1,ufmt + - name: msrv (esp32h2-hal) + run: cd esp32h2-hal/ && cargo check --features=eh1,ufmt msrv-xtensa: runs-on: ubuntu-latest @@ -305,6 +342,8 @@ jobs: run: cargo +stable clippy --manifest-path=esp32c3-hal/Cargo.toml -- --no-deps - name: clippy (esp32c6-hal) run: cargo +stable clippy --manifest-path=esp32c6-hal/Cargo.toml -- --no-deps + - name: clippy (esp32h2-hal) + run: cargo +stable clippy --manifest-path=esp32h2-hal/Cargo.toml -- --no-deps clippy-xtensa: runs-on: ubuntu-latest @@ -357,6 +396,8 @@ jobs: run: cargo fmt --all --manifest-path=esp32c3-hal/Cargo.toml -- --check - name: rustfmt (esp32c6-hal) run: cargo fmt --all --manifest-path=esp32c6-hal/Cargo.toml -- --check + - name: rustfmt (esp32h2-hal) + run: cargo fmt --all --manifest-path=esp32h2-hal/Cargo.toml -- --check - name: rustfmt (esp32s2-hal) run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check - name: rustfmt (esp32s3-hal) diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 1ef21d0ead7..356329cb66d 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -51,10 +51,10 @@ ufmt-write = { version = "0.1.0", optional = true } # Each supported device MUST have its PAC included below along with a # corresponding feature. esp32 = { version = "0.23.0", features = ["critical-section"], optional = true } -esp32c2 = { version = "0.10.0", features = ["critical-section"], optional = true } -esp32c3 = { version = "0.13.0", features = ["critical-section"], optional = true } -esp32c6 = { version = "0.3.0", features = ["critical-section"], optional = true } -esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "3db0042", package = "esp32h2", features = ["critical-section"], optional = true } +esp32c2 = { version = "0.11.0", features = ["critical-section"], optional = true } +esp32c3 = { version = "0.14.0", features = ["critical-section"], optional = true } +esp32c6 = { version = "0.4.0", features = ["critical-section"], optional = true } +esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "0ee1cea", package = "esp32h2", features = ["critical-section"], optional = true } esp32s2 = { version = "0.14.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.18.0", features = ["critical-section"], optional = true } diff --git a/esp-hal-common/devices/esp32h2.toml b/esp-hal-common/devices/esp32h2.toml index f3d47cf4266..6bd7a57b81a 100644 --- a/esp-hal-common/devices/esp32h2.toml +++ b/esp-hal-common/devices/esp32h2.toml @@ -1,5 +1,5 @@ [device] -arch = "riscv" +arch = "riscv" cores = "single_core" peripherals = [ @@ -18,8 +18,8 @@ peripherals = [ # "i2c0", # "i2c1", # "i2s0", - # "interrupt_core0", - # "intpri", + "interrupt_core0", + "intpri", # "io_mux", # "ledc", # "lp_ana", @@ -58,4 +58,8 @@ peripherals = [ # "uart1", # "uhci0", # "usb_device", + + + # Additional peripherals defined by us (the developers): + "plic", ] diff --git a/esp-hal-common/src/clock/clocks_ll/esp32h2.rs b/esp-hal-common/src/clock/clocks_ll/esp32h2.rs index 74a74b9d027..8cd6dabd07b 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32h2.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32h2.rs @@ -1,25 +1,360 @@ -use crate::clock::{ApbClock, CpuClock, PllClock, XtalClock}; +use crate::clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}; extern "C" { fn ets_update_cpu_frequency(ticks_per_us: u32); } +const I2C_BBPLL: u8 = 0x66; +const I2C_BBPLL_HOSTID: u8 = 0; +const I2C_BBPLL_OC_REF_DIV: u8 = 2; +const I2C_BBPLL_OC_REF_DIV_MSB: u8 = 3; +const I2C_BBPLL_OC_REF_DIV_LSB: u8 = 0; + +const I2C_BBPLL_OC_DIV: u8 = 3; +const I2C_BBPLL_OC_DIV_MSB: u8 = 5; +const I2C_BBPLL_OC_DIV_LSB: u8 = 0; + +const I2C_BBPLL_OC_DHREF_SEL: u8 = 5; +const I2C_BBPLL_OC_DHREF_SEL_MSB: u8 = 5; +const I2C_BBPLL_OC_DHREF_SEL_LSB: u8 = 4; + +const I2C_BBPLL_OC_DLREF_SEL: u8 = 5; +const I2C_BBPLL_OC_DLREF_SEL_MSB: u8 = 7; +const I2C_BBPLL_OC_DLREF_SEL_LSB: u8 = 6; + +const I2C_MST_ANA_CONF0_REG: u32 = 0x600AD800 + 0x18; +const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2; +const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3; +const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24; + +const MODEM_LPCON_CLK_CONF_FORCE_ON_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0xc; +const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2; + +// May be needed for enabling I2C clock +const MODEM_LPCON_I2C_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x8; +const MODEM_LPCON_CLK_I2C_SEL_96M: u32 = 1 << 0; + +const DR_REG_MODEM_LPCON_BASE: u32 = 0x600AD000; +const MODEM_LPCON_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x8; +const MODEM_LPCON_CLK_I2C_MST_EN: u32 = 1 << 2; + +const DR_REG_I2C_ANA_MST_BASE: u32 = 0x600AD800; +const I2C_MST_DATE_REG: u32 = DR_REG_I2C_ANA_MST_BASE + 0x34; +const I2C_MST_ANA_CONF2_REG: u32 = DR_REG_I2C_ANA_MST_BASE + 0x20; +const I2C_MST_ANA_CONF2: u32 = 0x00FFFFFF; +const I2C_MST_CLK_EN: u32 = 1 << 28; + +const REGI2C_BBPLL: u8 = 0x66; +const REGI2C_BIAS: u8 = 0x6a; +const REGI2C_PMU_REG: u8 = 0x6d; +const REGI2C_ULP_CAL: u8 = 0x61; +const REGI2C_SAR_I2C: u8 = 0x69; + +const REGI2C_BBPLL_DEVICE_EN: u32 = 1 << 9; // (1 << 5) << 4; +const REGI2C_BIAS_DEVICE_EN: u32 = 1 << 8; // (1 << 4) << 4; +const REGI2C_PMU_DEVICE_EN: u32 = 1 << 12; // (1 << 8) << 4; +const REGI2C_ULP_CAL_DEVICE_EN: u32 = 1 << 10; // (1 << 6) << 4; +const REGI2C_SAR_I2C_DEVICE_EN: u32 = 1 << 11; // (1 << 7) << 4; + +const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF; +const REGI2C_RTC_SLAVE_ID_S: u8 = 0; +const REGI2C_RTC_ADDR_V: u8 = 0xFF; +const REGI2C_RTC_ADDR_S: u8 = 8; +const REGI2C_RTC_WR_CNTL_V: u8 = 0x1; +const REGI2C_RTC_WR_CNTL_S: u8 = 24; +const REGI2C_RTC_DATA_V: u8 = 0xFF; +const REGI2C_RTC_DATA_S: u8 = 16; + +const I2C_MST_I2C0_CTRL_REG: u32 = DR_REG_I2C_ANA_MST_BASE + 0x0; +const REGI2C_RTC_BUSY: u32 = 1 << 25; + pub(crate) fn esp32h2_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) { - todo!() + unsafe { + // Enable I2C master clock + (MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile( + (MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).read_volatile() + | MODEM_LPCON_CLK_I2C_MST_FO, + ); + + // Set I2C clock to 96MHz + (MODEM_LPCON_I2C_CLK_CONF_REG as *mut u32).write_volatile( + (MODEM_LPCON_I2C_CLK_CONF_REG as *mut u32).read_volatile() + | MODEM_LPCON_CLK_I2C_SEL_96M, + ); + + let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32; + + // BPPLL calibration start + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH, + ); + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW, + ); + + let oc_ref_div = 0u32; + let oc_div = 1u32; + let oc_dhref_sel = 3u32; + let oc_dlref_sel = 1u32; + + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_REF_DIV, + I2C_BBPLL_OC_REF_DIV_MSB, + I2C_BBPLL_OC_REF_DIV_LSB, + oc_ref_div as u8, + ); + + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DIV, + I2C_BBPLL_OC_DIV_MSB, + I2C_BBPLL_OC_DIV_LSB, + oc_div as u8, + ); + + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DHREF_SEL, + I2C_BBPLL_OC_DHREF_SEL_MSB, + I2C_BBPLL_OC_DHREF_SEL_LSB, + oc_dhref_sel as u8, + ); + + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DLREF_SEL, + I2C_BBPLL_OC_DLREF_SEL_MSB, + I2C_BBPLL_OC_DLREF_SEL_LSB, + oc_dlref_sel as u8, + ); + + // WAIT CALIBRATION DONE + while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {} + + // BBPLL CALIBRATION STOP + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH, + ); + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW, + ); + } } pub(crate) fn esp32h2_rtc_bbpll_enable() { - todo!() + let pmu = unsafe { &*crate::peripherals::PMU::PTR }; + + pmu.imm_hp_ck_power.modify(|_, w| { + w.tie_high_xpd_bb_i2c() + .set_bit() + .tie_high_xpd_bbpll() + .set_bit() + .tie_high_xpd_bbpll_i2c() + .set_bit() + }); + + pmu.imm_hp_ck_power + .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit()); + + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + + // switch spimem to PLL 64Mhz clock + unsafe { + pcr.mspi_conf.modify(|_, w| w.mspi_clk_sel().bits(0b10)); + } } pub(crate) fn esp32h2_rtc_update_to_xtal(freq: XtalClock, _div: u8) { - todo!() + unsafe { + let pcr = &*crate::peripherals::PCR::PTR; + ets_update_cpu_frequency(freq.mhz()); + // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) + // first. + pcr.ahb_freq_conf + .modify(|_, w| w.ahb_div_num().bits(_div - 1)); + + pcr.cpu_freq_conf + .modify(|_, w| w.cpu_div_num().bits(_div - 1)); + // Switch clock source + pcr.sysclk_conf.modify(|_, w| w.soc_clk_sel().bits(0)); + + clk_ll_bus_update(); + } } pub(crate) fn esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) { - todo!() + let cpu_divider = 96 / cpu_clock_speed.mhz(); + clk_ll_cpu_set_divider(cpu_divider); + let ahb_divider = match cpu_divider { + 1 => 3, + 2 => 4, + _ => cpu_divider, + }; + clk_ll_ahb_set_divider(ahb_divider); + + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + + unsafe { + pcr.sysclk_conf.modify(|_, w| w.soc_clk_sel().bits(1)); + + clk_ll_bus_update(); + + ets_update_cpu_frequency(cpu_clock_speed.mhz()); + } } pub(crate) fn esp32h2_rtc_apb_freq_update(apb_freq: ApbClock) { - todo!() + let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; + let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) + | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); + + lp_aon + .store5 + .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) }); +} + +fn clk_ll_cpu_set_divider(divider: u32) { + assert!(divider >= 1); + + unsafe { + let pcr = &*crate::peripherals::PCR::PTR; + pcr.cpu_freq_conf + .modify(|_, w| w.cpu_div_num().bits((divider - 1) as u8)); + } +} + +fn clk_ll_ahb_set_divider(divider: u32) { + assert!(divider >= 1); + + unsafe { + let pcr = &*crate::peripherals::PCR::PTR; + pcr.ahb_freq_conf + .modify(|_, w| w.ahb_div_num().bits((divider - 1) as u8)); + } +} + +fn clk_ll_bus_update() { + unsafe { + let pcr = &*crate::peripherals::PCR::PTR; + + pcr.bus_clk_update + .modify(|_, w| w.bus_clock_update().bit(true)); + + // reg_get_bit + while pcr.bus_clk_update.read().bus_clock_update().bit_is_set() {} + } +} + +fn regi2c_enable_block(block: u8) { + reg_set_bit(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); + reg_set_bit(I2C_MST_DATE_REG, I2C_MST_CLK_EN); + + // Make I2C_MST_ANA_CONF2 in I2C_MST_ANA_CONF2_REG be 0 + unsafe { + (I2C_MST_ANA_CONF2_REG as *mut u32).write_volatile( + // (1 << 18) + (I2C_MST_ANA_CONF2_REG as *mut u32).read_volatile() & !(I2C_MST_ANA_CONF2 as u32), + ); + } + + // Before config I2C register, enable corresponding slave. + match block { + REGI2C_BBPLL => { + reg_set_bit(I2C_MST_ANA_CONF2_REG, REGI2C_BBPLL_DEVICE_EN); + } + REGI2C_BIAS => { + reg_set_bit(I2C_MST_ANA_CONF2_REG, REGI2C_BIAS_DEVICE_EN); + } + REGI2C_PMU_REG => { + reg_set_bit(I2C_MST_ANA_CONF2_REG, REGI2C_PMU_DEVICE_EN); + } + REGI2C_ULP_CAL => { + reg_set_bit(I2C_MST_ANA_CONF2_REG, REGI2C_ULP_CAL_DEVICE_EN); + } + REGI2C_SAR_I2C => { + reg_set_bit(I2C_MST_ANA_CONF2_REG, REGI2C_SAR_I2C_DEVICE_EN); + } + _ => (), + } +} + +fn regi2c_disable_block(block: u8) { + match block { + REGI2C_BBPLL => { + reg_clr_bit(I2C_MST_ANA_CONF2_REG, REGI2C_BBPLL_DEVICE_EN); + } + REGI2C_BIAS => { + reg_clr_bit(I2C_MST_ANA_CONF2_REG, REGI2C_BIAS_DEVICE_EN); + } + REGI2C_PMU_REG => { + reg_clr_bit(I2C_MST_ANA_CONF2_REG, REGI2C_PMU_DEVICE_EN); + } + REGI2C_ULP_CAL => { + reg_clr_bit(I2C_MST_ANA_CONF2_REG, REGI2C_ULP_CAL_DEVICE_EN); + } + REGI2C_SAR_I2C => { + reg_clr_bit(I2C_MST_ANA_CONF2_REG, REGI2C_SAR_I2C_DEVICE_EN); + } + _ => (), + } +} + +fn reg_set_bit(reg: u32, bit: u32) { + unsafe { + (reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | bit); + } +} + +fn reg_clr_bit(reg: u32, bit: u32) { + unsafe { + (reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !bit); + } +} + +fn reg_write(reg: u32, v: u32) { + unsafe { + (reg as *mut u32).write_volatile(v); + } +} + +fn reg_get_bit(reg: u32, b: u32) -> u32 { + unsafe { (reg as *mut u32).read_volatile() & b } +} + +fn reg_get_field(reg: u32, s: u32, v: u32) -> u32 { + unsafe { ((reg as *mut u32).read_volatile() >> s) & v } +} + +pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { + assert!(msb - lsb < 8); + regi2c_enable_block(block); + + // Read the i2c bus register + let mut temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) + << REGI2C_RTC_SLAVE_ID_S as u32) + | (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32; + reg_write(I2C_MST_I2C0_CTRL_REG, temp); + while reg_get_bit(I2C_MST_I2C0_CTRL_REG, REGI2C_RTC_BUSY) != 0 {} + temp = reg_get_field( + I2C_MST_I2C0_CTRL_REG, + REGI2C_RTC_DATA_S as u32, + REGI2C_RTC_DATA_V as u32, + ); + // Write the i2c bus register + temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1)); + temp = + ((data as u32 & (!(0xFFFFFFFF << (msb as u32 - lsb as u32 + 1)))) << (lsb as u32)) | temp; + temp = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32) + | ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32) + | ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32) + | ((temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32); + reg_write(I2C_MST_I2C0_CTRL_REG, temp); + while reg_get_bit(I2C_MST_I2C0_CTRL_REG, REGI2C_RTC_BUSY) != 0 {} + + regi2c_disable_block(block); } diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index b5d3b8d106f..193dd5cea83 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -31,6 +31,8 @@ pub trait Clock { #[derive(Debug, Clone, Copy)] pub enum CpuClock { Clock80MHz, + #[cfg(esp32h2)] + Clock96MHz, #[cfg(esp32c2)] Clock120MHz, #[cfg(not(esp32c2))] @@ -44,6 +46,8 @@ impl Clock for CpuClock { fn frequency(&self) -> HertzU32 { match self { CpuClock::Clock80MHz => HertzU32::MHz(80), + #[cfg(esp32h2)] + CpuClock::Clock96MHz => HertzU32::MHz(96), #[cfg(esp32c2)] CpuClock::Clock120MHz => HertzU32::MHz(120), #[cfg(not(esp32c2))] @@ -437,7 +441,15 @@ impl<'d> ClockControl<'d> { pub fn boot_defaults( clock_control: impl Peripheral
+ 'd, ) -> ClockControl<'d> { - todo!() + ClockControl { + _private: clock_control.into_ref(), + desired_rates: RawClocks { + cpu_clock: HertzU32::MHz(96), + apb_clock: HertzU32::MHz(32), + xtal_clock: HertzU32::MHz(32), + i2c_clock: HertzU32::MHz(32), + }, + } } /// Configure the CPU clock speed. @@ -446,7 +458,31 @@ impl<'d> ClockControl<'d> { clock_control: impl Peripheral
+ 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
- todo!()
+ let apb_freq;
+ let xtal_freq = XtalClock::RtcXtalFreqOther(32);
+ let pll_freq = PllClock::Pll320MHz;
+
+ if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
+ apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
+ clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1);
+ clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
+ } else {
+ apb_freq = ApbClock::ApbFreqOther(32);
+ clocks_ll::esp32h2_rtc_bbpll_enable();
+ clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq);
+ clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed);
+ clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
+ }
+
+ ClockControl {
+ _private: clock_control.into_ref(),
+ desired_rates: RawClocks {
+ cpu_clock: cpu_clock_speed.frequency(),
+ apb_clock: apb_freq.frequency(),
+ xtal_clock: xtal_freq.frequency(),
+ i2c_clock: HertzU32::MHz(32),
+ },
+ }
}
}
diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32h2.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32h2.rs
index b75a5af0b17..85eec95ea42 100644
--- a/esp-hal-common/src/rtc_cntl/rtc/esp32h2.rs
+++ b/esp-hal-common/src/rtc_cntl/rtc/esp32h2.rs
@@ -20,7 +20,48 @@ pub(crate) fn configure_clock() {
// Chip Reset: Reset the whole chip, including the analog part
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
-pub enum SocResetReason {}
+pub enum SocResetReason {
+ /// Power on reset
+ ///
+ /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
+ /// `ChipSuperWdt`, however that is not really compatible with Rust-style
+ /// enums.
+ ChipPowerOn = 0x01,
+ /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
+ CoreSw = 0x03,
+ /// Deep sleep reset the digital core
+ CoreDeepSleep = 0x05,
+ /// Main watch dog 0 resets digital core
+ CoreMwdt0 = 0x07,
+ /// Main watch dog 1 resets digital core
+ CoreMwdt1 = 0x08,
+ /// RTC watch dog resets digital core
+ CoreRtcWdt = 0x09,
+ /// Main watch dog 0 resets CPU 0
+ Cpu0Mwdt0 = 0x0B,
+ /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
+ Cpu0Sw = 0x0C,
+ /// RTC watch dog resets CPU 0
+ Cpu0RtcWdt = 0x0D,
+ /// VDD voltage is not stable and resets the digital core
+ SysBrownOut = 0x0F,
+ /// RTC watch dog resets digital core and rtc module
+ SysRtcWdt = 0x10,
+ /// Main watch dog 1 resets CPU 0
+ Cpu0Mwdt1 = 0x11,
+ /// Super watch dog resets the digital core and rtc module
+ SysSuperWdt = 0x12,
+ /// Glitch on clock resets the digital core and rtc module
+ SysClkGlitch = 0x13,
+ /// eFuse CRC error resets the digital core
+ CoreEfuseCrc = 0x14,
+ /// USB UART resets the digital core
+ CoreUsbUart = 0x15,
+ /// USB JTAG resets the digital core
+ CoreUsbJtag = 0x16,
+ /// Glitch on power resets the digital core
+ CorePwrGlitch = 0x17,
+}
/// RTC SLOW_CLK frequency values
#[derive(Debug, Clone, Copy)]
diff --git a/esp-hal-common/src/soc/esp32h2/mod.rs b/esp-hal-common/src/soc/esp32h2/mod.rs
index 8c121ca6b9d..310b8d7141c 100644
--- a/esp-hal-common/src/soc/esp32h2/mod.rs
+++ b/esp-hal-common/src/soc/esp32h2/mod.rs
@@ -4,5 +4,5 @@ pub mod peripherals;
pub mod radio_clocks;
pub(crate) mod registers {
- pub const INTERRUPT_MAP_BASE: u32 = 0x0; // FIXME
+ pub const INTERRUPT_MAP_BASE: u32 = 0x60010000;
}
diff --git a/esp-hal-common/src/soc/esp32h2/peripherals.rs b/esp-hal-common/src/soc/esp32h2/peripherals.rs
index 5931c83dd5b..ca30eceb480 100644
--- a/esp-hal-common/src/soc/esp32h2/peripherals.rs
+++ b/esp-hal-common/src/soc/esp32h2/peripherals.rs
@@ -20,8 +20,8 @@ crate::peripherals! {
// I2C0 => true,
// I2C1 => true,
// I2S0 => true,
- // INTERRUPT_CORE0 => true,
- // INTPRI => true,
+ INTERRUPT_CORE0 => true,
+ INTPRI => true,
// IO_MUX => true,
// LEDC => true,
// LP_ANA => true,
diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs
index beaa9772a20..644cf175634 100755
--- a/esp-hal-common/src/system.rs
+++ b/esp-hal-common/src/system.rs
@@ -79,15 +79,18 @@ pub enum Peripheral {
#[cfg(rsa)]
Rsa,
}
+
pub struct SoftwareInterruptControl {
_private: (),
}
+
impl SoftwareInterruptControl {
pub fn raise(&mut self, interrupt: SoftwareInterrupt) {
- #[cfg(not(esp32c6))]
+ #[cfg(not(any(esp32c6, esp32h2)))]
let system = unsafe { &*SystemPeripheral::PTR };
- #[cfg(esp32c6)]
+ #[cfg(any(esp32c6, esp32h2))]
let system = unsafe { &*IntPri::PTR };
+
match interrupt {
SoftwareInterrupt::SoftwareInterrupt0 => {
system
@@ -111,11 +114,13 @@ impl SoftwareInterruptControl {
}
}
}
+
pub fn reset(&mut self, interrupt: SoftwareInterrupt) {
- #[cfg(not(esp32c6))]
+ #[cfg(not(any(esp32c6, esp32h2)))]
let system = unsafe { &*SystemPeripheral::PTR };
- #[cfg(esp32c6)]
+ #[cfg(any(esp32c6, esp32h2))]
let system = unsafe { &*IntPri::PTR };
+
match interrupt {
SoftwareInterrupt::SoftwareInterrupt0 => {
system
diff --git a/esp32h2-hal/.cargo/config.toml b/esp32h2-hal/.cargo/config.toml
new file mode 100644
index 00000000000..3e8a0bd0188
--- /dev/null
+++ b/esp32h2-hal/.cargo/config.toml
@@ -0,0 +1,11 @@
+[target.riscv32imac-unknown-none-elf]
+runner = "espflash flash --monitor"
+rustflags = [
+ "-C", "link-arg=-Tlinkall.x",
+]
+
+[build]
+target = "riscv32imac-unknown-none-elf"
+
+[unstable]
+build-std = [ "core" ]
diff --git a/esp32h2-hal/Cargo.toml b/esp32h2-hal/Cargo.toml
new file mode 100644
index 00000000000..b987b52570c
--- /dev/null
+++ b/esp32h2-hal/Cargo.toml
@@ -0,0 +1,60 @@
+[package]
+name = "esp32h2-hal"
+version = "0.1.0"
+authors = [
+ "Kirill Mikhailov