mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-30 22:01:11 +00:00
Bare-bones support to run code on ULP-RV/LP core (#631)
* Bare-bones support to run code on ULP-RV/LP core * Add CHANGELOG.md entry
This commit is contained in:
parent
a86c2ac310
commit
996da27f30
@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Add octal PSRAM support for ESP32-S3 (#610)
|
- Add octal PSRAM support for ESP32-S3 (#610)
|
||||||
- Add MD5 functions from ESP ROM (#618)
|
- Add MD5 functions from ESP ROM (#618)
|
||||||
- Add embassy async `read` support for `uart` (#620)
|
- Add embassy async `read` support for `uart` (#620)
|
||||||
|
- Add bare-bones support to run code on ULP-RISCV / LP core (#631)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ peripherals = [
|
|||||||
"bt",
|
"bt",
|
||||||
"wifi",
|
"wifi",
|
||||||
"ieee802154",
|
"ieee802154",
|
||||||
|
"lp_core",
|
||||||
|
|
||||||
# ROM capabilities
|
# ROM capabilities
|
||||||
"rom_crc_le",
|
"rom_crc_le",
|
||||||
|
@ -54,6 +54,7 @@ peripherals = [
|
|||||||
"phy",
|
"phy",
|
||||||
"wifi",
|
"wifi",
|
||||||
"psram",
|
"psram",
|
||||||
|
"ulp_riscv_core",
|
||||||
|
|
||||||
# ROM capabilities
|
# ROM capabilities
|
||||||
"rom_crc_le",
|
"rom_crc_le",
|
||||||
|
@ -66,6 +66,7 @@ peripherals = [
|
|||||||
"bt",
|
"bt",
|
||||||
"wifi",
|
"wifi",
|
||||||
"psram",
|
"psram",
|
||||||
|
"ulp_riscv_core",
|
||||||
|
|
||||||
# ROM capabilities
|
# ROM capabilities
|
||||||
"rom_crc_le",
|
"rom_crc_le",
|
||||||
|
@ -62,9 +62,13 @@ pub use self::rtc_cntl::{Rtc, Rwdt};
|
|||||||
pub use self::soc::cpu_control;
|
pub use self::soc::cpu_control;
|
||||||
#[cfg(efuse)]
|
#[cfg(efuse)]
|
||||||
pub use self::soc::efuse;
|
pub use self::soc::efuse;
|
||||||
|
#[cfg(lp_core)]
|
||||||
|
pub use self::soc::lp_core;
|
||||||
pub use self::soc::peripherals;
|
pub use self::soc::peripherals;
|
||||||
#[cfg(psram)]
|
#[cfg(psram)]
|
||||||
pub use self::soc::psram;
|
pub use self::soc::psram;
|
||||||
|
#[cfg(ulp_riscv_core)]
|
||||||
|
pub use self::soc::ulp_core;
|
||||||
#[cfg(any(spi0, spi1, spi2, spi3))]
|
#[cfg(any(spi0, spi1, spi2, spi3))]
|
||||||
pub use self::spi::Spi;
|
pub use self::spi::Spi;
|
||||||
#[cfg(any(timg0, timg1))]
|
#[cfg(any(timg0, timg1))]
|
||||||
|
79
esp-hal-common/src/soc/esp32c6/lp_core.rs
Normal file
79
esp-hal-common/src/soc/esp32c6/lp_core.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! Control the LP core
|
||||||
|
|
||||||
|
use esp32c6 as pac;
|
||||||
|
|
||||||
|
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum LpCoreWakeupSource {
|
||||||
|
HpCpu,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LpCore<'d> {
|
||||||
|
_lp_core: PeripheralRef<'d, crate::soc::peripherals::LP_CORE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> LpCore<'d> {
|
||||||
|
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::LP_CORE> + 'd) -> Self {
|
||||||
|
crate::into_ref!(lp_core);
|
||||||
|
Self { _lp_core: lp_core }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
ulp_lp_core_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self, wakeup_src: LpCoreWakeupSource) {
|
||||||
|
ulp_lp_core_run(wakeup_src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_lp_core_stop() {
|
||||||
|
let pmu = unsafe { &*pac::PMU::PTR };
|
||||||
|
pmu.lp_cpu_pwr1
|
||||||
|
.modify(|_, w| unsafe { w.lp_cpu_wakeup_en().bits(0) });
|
||||||
|
pmu.lp_cpu_pwr1
|
||||||
|
.modify(|_, w| w.lp_cpu_sleep_req().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_lp_core_run(wakeup_src: LpCoreWakeupSource) {
|
||||||
|
let lp_aon = unsafe { &*pac::LP_AON::PTR };
|
||||||
|
let pmu = unsafe { &*pac::PMU::PTR };
|
||||||
|
let lp_peri = unsafe { &*pac::LP_PERI::PTR };
|
||||||
|
|
||||||
|
// Enable LP-Core
|
||||||
|
lp_aon.lpcore.modify(|_, w| w.disable().clear_bit());
|
||||||
|
|
||||||
|
// Allow LP core to access LP memory during sleep
|
||||||
|
lp_aon.lpbus.modify(|_, w| w.fast_mem_mux_sel().clear_bit());
|
||||||
|
lp_aon
|
||||||
|
.lpbus
|
||||||
|
.modify(|_, w| w.fast_mem_mux_sel_update().set_bit());
|
||||||
|
|
||||||
|
// Enable stall at sleep request
|
||||||
|
pmu.lp_cpu_pwr0
|
||||||
|
.modify(|_, w| w.lp_cpu_slp_stall_en().set_bit());
|
||||||
|
|
||||||
|
// Enable reset after wake-up
|
||||||
|
pmu.lp_cpu_pwr0
|
||||||
|
.modify(|_, w| w.lp_cpu_slp_reset_en().set_bit());
|
||||||
|
|
||||||
|
// Set wake-up sources
|
||||||
|
let src = match wakeup_src {
|
||||||
|
LpCoreWakeupSource::HpCpu => 0x01,
|
||||||
|
};
|
||||||
|
pmu.lp_cpu_pwr1
|
||||||
|
.modify(|_, w| w.lp_cpu_wakeup_en().variant(src));
|
||||||
|
|
||||||
|
// Enable JTAG debugging
|
||||||
|
lp_peri
|
||||||
|
.cpu
|
||||||
|
.modify(|_, w| w.lpcore_dbgm_unavaliable().clear_bit());
|
||||||
|
|
||||||
|
// wake up
|
||||||
|
match wakeup_src {
|
||||||
|
LpCoreWakeupSource::HpCpu => {
|
||||||
|
pmu.hp_lp_cpu_comm.write(|w| w.hp_trigger_lp().set_bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
pub mod efuse;
|
pub mod efuse;
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
|
pub mod lp_core;
|
||||||
pub mod peripherals;
|
pub mod peripherals;
|
||||||
pub mod radio_clocks;
|
pub mod radio_clocks;
|
||||||
|
|
||||||
|
@ -71,4 +71,5 @@ crate::peripherals! {
|
|||||||
UHCI0 => true,
|
UHCI0 => true,
|
||||||
USB_DEVICE => true,
|
USB_DEVICE => true,
|
||||||
RADIO => false,
|
RADIO => false,
|
||||||
|
LP_CORE => false,
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ pub mod peripherals;
|
|||||||
#[cfg(psram)]
|
#[cfg(psram)]
|
||||||
pub mod psram;
|
pub mod psram;
|
||||||
pub mod radio_clocks;
|
pub mod radio_clocks;
|
||||||
|
pub mod ulp_core;
|
||||||
|
|
||||||
pub(crate) mod constants {
|
pub(crate) mod constants {
|
||||||
pub const I2S_SCLK: u32 = 160_000_000;
|
pub const I2S_SCLK: u32 = 160_000_000;
|
||||||
|
@ -51,4 +51,5 @@ crate::peripherals! {
|
|||||||
XTS_AES => true,
|
XTS_AES => true,
|
||||||
RADIO => false,
|
RADIO => false,
|
||||||
PSRAM => false,
|
PSRAM => false,
|
||||||
|
ULP_RISCV_CORE => false,
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const PSRAM_VADDR: u32 = 0x3f500000;
|
const PSRAM_VADDR: u32 = 0x3f500000;
|
||||||
|
|
||||||
pub fn psram_vaddr_start() -> usize {
|
pub fn psram_vaddr_start() -> usize {
|
||||||
unsafe { PSRAM_VADDR_START as usize }
|
PSRAM_VADDR_START as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
|
109
esp-hal-common/src/soc/esp32s2/ulp_core.rs
Normal file
109
esp-hal-common/src/soc/esp32s2/ulp_core.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//! Control the ULP RISCV core
|
||||||
|
|
||||||
|
use esp32s2 as pac;
|
||||||
|
|
||||||
|
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn ets_delay_us(delay: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum UlpCoreWakeupSource {
|
||||||
|
HpCpu,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UlpCore<'d> {
|
||||||
|
_lp_core: PeripheralRef<'d, crate::soc::peripherals::ULP_RISCV_CORE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> UlpCore<'d> {
|
||||||
|
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::ULP_RISCV_CORE> + 'd) -> Self {
|
||||||
|
crate::into_ref!(lp_core);
|
||||||
|
Self { _lp_core: lp_core }
|
||||||
|
}
|
||||||
|
|
||||||
|
// currently stopping the ULP doesn't work (while following the proedures
|
||||||
|
// outlines in the TRM) - so don't offer this funtion for now
|
||||||
|
//
|
||||||
|
// pub fn stop(&mut self) {
|
||||||
|
// ulp_stop();
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn run(&mut self, wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
ulp_run(wakeup_src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_stop() {
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
|
||||||
|
|
||||||
|
// suspends the ulp operation
|
||||||
|
rtc_cntl.cocpu_ctrl.modify(|_, w| w.cocpu_done().set_bit());
|
||||||
|
|
||||||
|
// Resets the processor
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_run(wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
|
||||||
|
// Reset COCPU when power on
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
|
||||||
|
|
||||||
|
// Disable ULP timer
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
|
||||||
|
|
||||||
|
// wait for at least 1 RTC_SLOW_CLK cycle
|
||||||
|
unsafe {
|
||||||
|
ets_delay_us(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select ULP-RISC-V to send the DONE signal
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_done_force().set_bit());
|
||||||
|
|
||||||
|
ulp_config_wakeup_source(wakeup_src);
|
||||||
|
|
||||||
|
// Select RISC-V as the ULP_TIMER trigger target
|
||||||
|
rtc_cntl.cocpu_ctrl.modify(|_, w| w.cocpu_sel().clear_bit());
|
||||||
|
|
||||||
|
// Clear any spurious wakeup trigger interrupts upon ULP startup
|
||||||
|
unsafe {
|
||||||
|
ets_delay_us(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_cntl.int_clr_rtc.write(|w| {
|
||||||
|
w.cocpu_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.cocpu_trap_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.ulp_cp_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_config_wakeup_source(wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
match wakeup_src {
|
||||||
|
UlpCoreWakeupSource::HpCpu => {
|
||||||
|
// use timer to wake up
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_ctrl
|
||||||
|
.modify(|_, w| w.ulp_cp_force_start_top().clear_bit());
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().set_bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ pub mod peripherals;
|
|||||||
#[cfg(psram)]
|
#[cfg(psram)]
|
||||||
pub mod psram;
|
pub mod psram;
|
||||||
pub mod radio_clocks;
|
pub mod radio_clocks;
|
||||||
|
pub mod ulp_core;
|
||||||
|
|
||||||
pub(crate) mod constants {
|
pub(crate) mod constants {
|
||||||
pub const I2S_SCLK: u32 = 160_000_000;
|
pub const I2S_SCLK: u32 = 160_000_000;
|
||||||
|
@ -62,4 +62,5 @@ crate::peripherals! {
|
|||||||
XTS_AES => true,
|
XTS_AES => true,
|
||||||
RADIO => false,
|
RADIO => false,
|
||||||
PSRAM => false,
|
PSRAM => false,
|
||||||
|
ULP_RISCV_CORE => false,
|
||||||
}
|
}
|
||||||
|
138
esp-hal-common/src/soc/esp32s3/ulp_core.rs
Normal file
138
esp-hal-common/src/soc/esp32s3/ulp_core.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
//! Control the ULP RISCV core
|
||||||
|
|
||||||
|
use esp32s3 as pac;
|
||||||
|
|
||||||
|
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn ets_delay_us(delay: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum UlpCoreWakeupSource {
|
||||||
|
HpCpu,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UlpCore<'d> {
|
||||||
|
_lp_core: PeripheralRef<'d, crate::soc::peripherals::ULP_RISCV_CORE>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> UlpCore<'d> {
|
||||||
|
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::ULP_RISCV_CORE> + 'd) -> Self {
|
||||||
|
crate::into_ref!(lp_core);
|
||||||
|
Self { _lp_core: lp_core }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
ulp_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self, wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
ulp_run(wakeup_src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_stop() {
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
|
||||||
|
|
||||||
|
// suspends the ulp operation
|
||||||
|
rtc_cntl.cocpu_ctrl.modify(|_, w| w.cocpu_done().set_bit());
|
||||||
|
|
||||||
|
// Resets the processor
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ets_delay_us(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// above doesn't seem to halt the ULP core - this will
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_clkgate_en().clear_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_run(wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
|
||||||
|
// Reset COCPU when power on
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
|
||||||
|
|
||||||
|
// The coprocessor cpu trap signal doesnt have a stable reset value,
|
||||||
|
// force ULP-RISC-V clock on to stop RTC_COCPU_TRAP_TRIG_EN from waking the CPU
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_clk_fo().set_bit());
|
||||||
|
|
||||||
|
// Disable ULP timer
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
|
||||||
|
|
||||||
|
// wait for at least 1 RTC_SLOW_CLK cycle
|
||||||
|
unsafe {
|
||||||
|
ets_delay_us(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do not select RISC-V as the Coprocessor here as this could lead to a hang
|
||||||
|
// in the main CPU. Instead, we reset RTC_CNTL_COCPU_SEL after we have enabled
|
||||||
|
// the ULP timer.
|
||||||
|
//
|
||||||
|
// IDF-4510
|
||||||
|
|
||||||
|
// Select ULP-RISC-V to send the DONE signal
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_done_force().set_bit());
|
||||||
|
|
||||||
|
// Set the CLKGATE_EN signal
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_clkgate_en().set_bit());
|
||||||
|
|
||||||
|
ulp_config_wakeup_source(wakeup_src);
|
||||||
|
|
||||||
|
// Select RISC-V as the ULP_TIMER trigger target
|
||||||
|
// Selecting the RISC-V as the Coprocessor at the end is a workaround
|
||||||
|
// for the hang issue recorded in IDF-4510.
|
||||||
|
rtc_cntl.cocpu_ctrl.modify(|_, w| w.cocpu_sel().clear_bit());
|
||||||
|
|
||||||
|
// Clear any spurious wakeup trigger interrupts upon ULP startup
|
||||||
|
unsafe {
|
||||||
|
ets_delay_us(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_cntl.int_clr_rtc.write(|w| {
|
||||||
|
w.cocpu_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.cocpu_trap_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.ulp_cp_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
});
|
||||||
|
|
||||||
|
rtc_cntl
|
||||||
|
.cocpu_ctrl
|
||||||
|
.modify(|_, w| w.cocpu_clkgate_en().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ulp_config_wakeup_source(wakeup_src: UlpCoreWakeupSource) {
|
||||||
|
match wakeup_src {
|
||||||
|
UlpCoreWakeupSource::HpCpu => {
|
||||||
|
// use timer to wake up
|
||||||
|
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_ctrl
|
||||||
|
.modify(|_, w| w.ulp_cp_force_start_top().clear_bit());
|
||||||
|
rtc_cntl
|
||||||
|
.ulp_cp_timer
|
||||||
|
.modify(|_, w| w.ulp_cp_slp_timer_en().set_bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
esp32c6-hal/examples/lp_core_basic.rs
Normal file
83
esp32c6-hal/examples/lp_core_basic.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//! This shows a very basic example of running code on the LP core.
|
||||||
|
//!
|
||||||
|
//! Code on LP core just increments a counter. The current value is printed by
|
||||||
|
//! the HP core.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32c6_hal::{
|
||||||
|
clock::ClockControl,
|
||||||
|
peripherals::Peripherals,
|
||||||
|
prelude::*,
|
||||||
|
timer::TimerGroup,
|
||||||
|
Rtc,
|
||||||
|
};
|
||||||
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::lp_core;
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
// 50000000 <_start>:
|
||||||
|
// 50000000: 00000517 auipc a0,0x0
|
||||||
|
// 50000004: 01050513 addi a0,a0,16 # 50000010 <data>
|
||||||
|
// 50000008: 4581 li a1,0
|
||||||
|
//
|
||||||
|
// 5000000a <_loop>:
|
||||||
|
// 5000000a: 0585 addi a1,a1,1
|
||||||
|
// 5000000c: c10c sw a1,0(a0)
|
||||||
|
// 5000000e: bff5 j 5000000a <_loop>
|
||||||
|
//
|
||||||
|
// 50000010 <data>:
|
||||||
|
// 50000010: 0000 0000
|
||||||
|
|
||||||
|
const CODE: &[u8] = &[
|
||||||
|
0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x01, 0x81, 0x45, 0x85, 0x05, 0x0c, 0xc1, 0xf5, 0xbf,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = Peripherals::take();
|
||||||
|
let mut system = peripherals.PCR.split();
|
||||||
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
|
let mut rtc = Rtc::new(peripherals.LP_CLKRST);
|
||||||
|
let timer_group0 = TimerGroup::new(
|
||||||
|
peripherals.TIMG0,
|
||||||
|
&clocks,
|
||||||
|
&mut system.peripheral_clock_control,
|
||||||
|
);
|
||||||
|
let mut wdt0 = timer_group0.wdt;
|
||||||
|
let timer_group1 = TimerGroup::new(
|
||||||
|
peripherals.TIMG1,
|
||||||
|
&clocks,
|
||||||
|
&mut system.peripheral_clock_control,
|
||||||
|
);
|
||||||
|
let mut wdt1 = timer_group1.wdt;
|
||||||
|
|
||||||
|
// Disable watchdog timers
|
||||||
|
rtc.swd.disable();
|
||||||
|
rtc.rwdt.disable();
|
||||||
|
wdt0.disable();
|
||||||
|
wdt1.disable();
|
||||||
|
|
||||||
|
let mut lp_core = esp32c6_hal::lp_core::LpCore::new(peripherals.LP_CORE);
|
||||||
|
lp_core.stop();
|
||||||
|
println!("lp core stopped");
|
||||||
|
|
||||||
|
// copy code to LP ram
|
||||||
|
let lp_ram = 0x5000_0000 as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
|
||||||
|
}
|
||||||
|
println!("copied code (len {})", CODE.len());
|
||||||
|
|
||||||
|
// start LP core
|
||||||
|
lp_core.run(lp_core::LpCoreWakeupSource::HpCpu);
|
||||||
|
println!("lpcore run");
|
||||||
|
|
||||||
|
let data = (0x5000_0010 - 0) as *mut u32;
|
||||||
|
loop {
|
||||||
|
println!("Current {}", unsafe { data.read_volatile() });
|
||||||
|
}
|
||||||
|
}
|
72
esp32s2-hal/examples/ulp_riscv_core_basic.rs
Normal file
72
esp32s2-hal/examples/ulp_riscv_core_basic.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//! This shows a very basic example of running code on the ULP RISCV core.
|
||||||
|
//!
|
||||||
|
//! Code on ULP core just increments a counter. The current value is printed by
|
||||||
|
//! the HP core.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32s2_hal::{
|
||||||
|
clock::ClockControl,
|
||||||
|
peripherals::Peripherals,
|
||||||
|
prelude::*,
|
||||||
|
timer::TimerGroup,
|
||||||
|
Rtc,
|
||||||
|
};
|
||||||
|
use esp_backtrace as _;
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
// 50000000 <_start>:
|
||||||
|
// 50000000: 00000517 auipc a0,0x0
|
||||||
|
// 50000004: 01050513 addi a0,a0,16 # 50000010 <data>
|
||||||
|
// 50000008: 4581 li a1,0
|
||||||
|
//
|
||||||
|
// 5000000a <_loop>:
|
||||||
|
// 5000000a: 0585 addi a1,a1,1
|
||||||
|
// 5000000c: c10c sw a1,0(a0)
|
||||||
|
// 5000000e: bff5 j 5000000a <_loop>
|
||||||
|
//
|
||||||
|
// 50000010 <data>:
|
||||||
|
// 50000010: 0000 0000
|
||||||
|
|
||||||
|
const CODE: &[u8] = &[
|
||||||
|
0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x01, 0x81, 0x45, 0x85, 0x05, 0x0c, 0xc1, 0xf5, 0xbf,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = Peripherals::take();
|
||||||
|
let mut system = peripherals.SYSTEM.split();
|
||||||
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
|
let timer_group0 = TimerGroup::new(
|
||||||
|
peripherals.TIMG0,
|
||||||
|
&clocks,
|
||||||
|
&mut system.peripheral_clock_control,
|
||||||
|
);
|
||||||
|
let mut wdt = timer_group0.wdt;
|
||||||
|
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
|
||||||
|
|
||||||
|
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||||
|
wdt.disable();
|
||||||
|
rtc.rwdt.disable();
|
||||||
|
|
||||||
|
let mut ulp_core = esp32s2_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||||
|
|
||||||
|
// copy code to RTC ram
|
||||||
|
let lp_ram = 0x5000_0000 as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
|
||||||
|
}
|
||||||
|
println!("copied code (len {})", CODE.len());
|
||||||
|
|
||||||
|
// start ULP core
|
||||||
|
ulp_core.run(esp32s2_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||||
|
println!("ulpcore run");
|
||||||
|
|
||||||
|
let data = (0x5000_0010 - 0) as *mut u32;
|
||||||
|
loop {
|
||||||
|
println!("Current {}", unsafe { data.read_volatile() });
|
||||||
|
}
|
||||||
|
}
|
74
esp32s3-hal/examples/ulp_riscv_core_basic.rs
Normal file
74
esp32s3-hal/examples/ulp_riscv_core_basic.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//! This shows a very basic example of running code on the ULP RISCV core.
|
||||||
|
//!
|
||||||
|
//! Code on ULP core just increments a counter. The current value is printed by
|
||||||
|
//! the HP core.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32s3_hal::{
|
||||||
|
clock::ClockControl,
|
||||||
|
peripherals::Peripherals,
|
||||||
|
prelude::*,
|
||||||
|
timer::TimerGroup,
|
||||||
|
Rtc,
|
||||||
|
};
|
||||||
|
use esp_backtrace as _;
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
// 50000000 <_start>:
|
||||||
|
// 50000000: 00000517 auipc a0,0x0
|
||||||
|
// 50000004: 01050513 addi a0,a0,16 # 50000010 <data>
|
||||||
|
// 50000008: 4581 li a1,0
|
||||||
|
//
|
||||||
|
// 5000000a <_loop>:
|
||||||
|
// 5000000a: 0585 addi a1,a1,1
|
||||||
|
// 5000000c: c10c sw a1,0(a0)
|
||||||
|
// 5000000e: bff5 j 5000000a <_loop>
|
||||||
|
//
|
||||||
|
// 50000010 <data>:
|
||||||
|
// 50000010: 0000 0000
|
||||||
|
|
||||||
|
const CODE: &[u8] = &[
|
||||||
|
0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x01, 0x81, 0x45, 0x85, 0x05, 0x0c, 0xc1, 0xf5, 0xbf,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = Peripherals::take();
|
||||||
|
let mut system = peripherals.SYSTEM.split();
|
||||||
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
|
let timer_group0 = TimerGroup::new(
|
||||||
|
peripherals.TIMG0,
|
||||||
|
&clocks,
|
||||||
|
&mut system.peripheral_clock_control,
|
||||||
|
);
|
||||||
|
let mut wdt = timer_group0.wdt;
|
||||||
|
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
|
||||||
|
|
||||||
|
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||||
|
wdt.disable();
|
||||||
|
rtc.rwdt.disable();
|
||||||
|
|
||||||
|
let mut ulp_core = esp32s3_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||||
|
ulp_core.stop();
|
||||||
|
println!("ulp core stopped");
|
||||||
|
|
||||||
|
// copy code to RTC ram
|
||||||
|
let lp_ram = 0x5000_0000 as *mut u8;
|
||||||
|
unsafe {
|
||||||
|
core::ptr::copy_nonoverlapping(CODE as *const _ as *const u8, lp_ram, CODE.len());
|
||||||
|
}
|
||||||
|
println!("copied code (len {})", CODE.len());
|
||||||
|
|
||||||
|
// start ULP core
|
||||||
|
ulp_core.run(esp32s3_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||||
|
println!("ulpcore run");
|
||||||
|
|
||||||
|
let data = (0x5000_0010 - 0) as *mut u32;
|
||||||
|
loop {
|
||||||
|
println!("Current {}", unsafe { data.read_volatile() });
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user