Skip to content

Commit

Permalink
Create safe wrappers for some ROM functions in the rom module (#1290)
Browse files Browse the repository at this point in the history
* Create safe wrappers for some ROM functions in the `rom` module

* Replace transmute in ESP32-S3's `cpu_control` module with ROM function

* Inline *all* the things!

* Remove duplicate of `rom::regi2c_write` with ROM function
  • Loading branch information
jessebraham authored Mar 14, 2024
1 parent 3079d9c commit b402692
Show file tree
Hide file tree
Showing 18 changed files with 263 additions and 377 deletions.
1 change: 0 additions & 1 deletion esp-hal/ld/esp32c6/rom-functions.x
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ets_printf = 0x40000028;
ets_update_cpu_frequency = ets_update_cpu_frequency_rom;
PROVIDE(esp_rom_printf = ets_printf);
PROVIDE(cache_invalidate_icache_all = 0x4000064c);
PROVIDE(cache_suspend_icache = 0x40000698);
Expand Down
3 changes: 1 addition & 2 deletions esp-hal/ld/esp32h2/rom-functions.x
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ets_printf = 0x40000028;
ets_update_cpu_frequency = ets_update_cpu_frequency_rom;
PROVIDE(esp_rom_printf = ets_printf);
PROVIDE(cache_invalidate_icache_all = 0x40000620);
PROVIDE(cache_suspend_icache = 0x4000066c);
Expand Down Expand Up @@ -27,4 +26,4 @@ PROVIDE(esp_rom_md5_final = 0x40000720);
memset = 0x400004a0;
memcpy = 0x400004a4;
memmove = 0x400004a8;
memcmp = 0x400004ac;
memcmp = 0x400004ac;
3 changes: 2 additions & 1 deletion esp-hal/ld/esp32s3/rom-functions.x
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ PROVIDE(Cache_Resume_DCache = 0x400018c0 );
PROVIDE(rom_config_data_cache_mode = 0x40001a28 );
PROVIDE(rom_config_instruction_cache_mode = 0x40001a1c );
PROVIDE(ets_efuse_get_wp_pad = 0x40001fa4);
PROVIDE(ets_set_appcpu_boot_addr = 0x40000720);

PROVIDE(esp_rom_crc32_be = 0x40001ca4);
PROVIDE(esp_rom_crc16_be = 0x40001cbc);
Expand All @@ -38,4 +39,4 @@ PROVIDE( esp_rom_opiflash_pin_config = 0x40000894 );
memset = 0x400011e8;
memcpy = 0x400011f4;
memmove = 0x40001200;
memcmp = 0x4000120c;
memcmp = 0x4000120c;
7 changes: 1 addition & 6 deletions esp-hal/src/analog/adc/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,12 +592,7 @@ where
// the delay might be a bit generous but longer delay seem to not cause problems
#[cfg(esp32c6)]
{
extern "C" {
fn ets_delay_us(us: u32);
}
unsafe {
ets_delay_us(40);
}
crate::rom::ets_delay_us(40);
ADCI::start_onetime_sample();
}
}
Expand Down
280 changes: 105 additions & 175 deletions esp-hal/src/clock/clocks_ll/esp32.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::clock::{Clock, PllClock, XtalClock};
use crate::{
clock::{Clock, PllClock, XtalClock},
regi2c_write,
};

const REF_CLK_FREQ: u32 = 1000000;

Expand Down Expand Up @@ -42,148 +45,108 @@ pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock
let efuse = unsafe { &*crate::peripherals::EFUSE::ptr() };
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };

unsafe {
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;

let div_ref: u32;
let div7_0: u32;
let div10_8: u32;
let lref: u32;
let dcur: u32;
let bw: u32;

if matches!(pll_freq, PllClock::Pll320MHz) {
// Raise the voltage, if needed
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(DIG_DBIAS_80M_160M as u8));

// Configure 320M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 32;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}

XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}

XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
let div_ref: u32;
let div7_0: u32;
let div10_8: u32;
let lref: u32;
let dcur: u32;
let bw: u32;

if matches!(pll_freq, PllClock::Pll320MHz) {
// Raise the voltage, if needed
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(DIG_DBIAS_80M_160M as u8));

// Configure 320M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 32;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}

i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_ENDIV5,
BBPLL_ENDIV5_VAL_320M,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_DSMP,
BBPLL_BBADC_DSMP_VAL_320M,
);
} else {
// Raise the voltage
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(dig_dbias_240_m as u8));

// Configure 480M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 28;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}

XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}

XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}

i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_ENDIV5,
BBPLL_ENDIV5_VAL_480M,
);

i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_DSMP,
BBPLL_BBADC_DSMP_VAL_480M,
);
XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}

let i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref);
let i2c_bbpll_div_7_0 = div7_0;
let i2c_bbpll_dcur = (bw << 6) | dcur;
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_LREF,
i2c_bbpll_lref,
);

i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV_7_0,
i2c_bbpll_div_7_0,
);

i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DCUR,
i2c_bbpll_dcur,
);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_320M);
} else {
// Raise the voltage
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(dig_dbias_240_m as u8));

// Configure 480M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 28;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}

XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}

XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}

regi2c_write!(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M);
}

let i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref);
let i2c_bbpll_div_7_0 = div7_0;
let i2c_bbpll_dcur = (bw << 6) | dcur;

regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
}

pub(crate) fn esp32_rtc_bbpll_enable() {
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };

unsafe {
rtc_cntl.options0().modify(|_, w| {
unsafe { &*crate::peripherals::RTC_CNTL::ptr() }
.options0()
.modify(|_, w| {
w.bias_i2c_force_pd()
.clear_bit()
.bb_i2c_force_pd()
Expand All @@ -194,49 +157,16 @@ pub(crate) fn esp32_rtc_bbpll_enable() {
.clear_bit()
});

// reset BBPLL configuration
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_IR_CAL_DELAY,
BBPLL_IR_CAL_DELAY_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_IR_CAL_EXT_CAP,
BBPLL_IR_CAL_EXT_CAP_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_ENB_FCAL,
BBPLL_OC_ENB_FCAL_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_ENB_VCON,
BBPLL_OC_ENB_VCON_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_CAL_7_0,
BBPLL_BBADC_CAL_7_0_VAL,
);
}
}

#[inline(always)]
unsafe fn i2c_writereg_rtc(block: u32, block_hostid: u32, reg_add: u32, indata: u32) {
const ROM_I2C_WRITEREG: u32 = 0x400041a4;

// cast to usize is just needed because of the way we run clippy in CI
let rom_i2c_writereg: fn(block: u32, block_hostid: u32, reg_add: u32, indata: u32) -> i32 =
core::mem::transmute(ROM_I2C_WRITEREG as usize);

rom_i2c_writereg(block, block_hostid, reg_add, indata);
// reset BBPLL configuration
regi2c_write!(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, BBPLL_IR_CAL_DELAY_VAL);
regi2c_write!(
I2C_BBPLL,
I2C_BBPLL_IR_CAL_EXT_CAP,
BBPLL_IR_CAL_EXT_CAP_VAL
);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, BBPLL_OC_ENB_FCAL_VAL);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, BBPLL_OC_ENB_VCON_VAL);
regi2c_write!(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, BBPLL_BBADC_CAL_7_0_VAL);
}

pub(crate) fn esp32_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
Expand Down
11 changes: 4 additions & 7 deletions esp-hal/src/clock/clocks_ll/esp32c2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ use crate::{
regi2c_write_mask,
};

extern "C" {
fn ets_update_cpu_frequency_rom(ticks_per_us: u32);
}

const I2C_BBPLL: u32 = 0x66;
const I2C_BBPLL_HOSTID: u32 = 0;

Expand Down Expand Up @@ -123,10 +119,10 @@ pub(crate) fn esp32c2_rtc_bbpll_enable() {
}

pub(crate) fn esp32c2_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
let system_control = unsafe { &*crate::peripherals::SYSTEM::ptr() };
crate::rom::ets_update_cpu_frequency_rom(freq.mhz());

let system_control = unsafe { &*crate::peripherals::SYSTEM::ptr() };
unsafe {
ets_update_cpu_frequency_rom(freq.mhz());
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
system_control.sysclk_conf().modify(|_, w| {
Expand Down Expand Up @@ -158,8 +154,9 @@ pub(crate) fn esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
CpuClock::Clock120MHz => 1,
})
});
ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
}

crate::rom::ets_update_cpu_frequency_rom(cpu_clock_speed.mhz());
}

pub(crate) fn esp32c2_rtc_apb_freq_update(apb_freq: ApbClock) {
Expand Down
Loading

0 comments on commit b402692

Please sign in to comment.