esp_lp_hal/
lib.rs
1#![doc = document_features::document_features!()]
12#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
13#![allow(asm_sub_register)]
14#![deny(missing_docs)]
15#![no_std]
16
17use core::arch::global_asm;
18
19pub mod delay;
20pub mod gpio;
21#[cfg(esp32c6)]
22pub mod i2c;
23#[cfg(esp32c6)]
24pub mod uart;
25
26#[cfg(feature = "esp32c6")]
27pub use esp32c6_lp as pac;
28#[cfg(feature = "esp32s2")]
29pub use esp32s2_ulp as pac;
30#[cfg(feature = "esp32s3")]
31pub use esp32s3_ulp as pac;
32
33pub mod prelude {
35 pub use procmacros::entry;
36}
37
38cfg_if::cfg_if! {
39 if #[cfg(feature = "esp32c6")] {
40 const LP_FAST_CLK_HZ: u32 = 16_000_000;
42 const XTAL_D2_CLK_HZ: u32 = 20_000_000;
43 } else if #[cfg(feature = "esp32s2")] {
44 const LP_FAST_CLK_HZ: u32 = 8_000_000;
45 } else if #[cfg(feature = "esp32s3")] {
46 const LP_FAST_CLK_HZ: u32 = 17_500_000;
47 }
48}
49
50pub(crate) static mut CPU_CLOCK: u32 = LP_FAST_CLK_HZ;
51
52#[cfg(feature = "esp32c6")]
54pub fn wake_hp_core() {
55 unsafe { &*esp32c6_lp::PMU::PTR }
56 .hp_lp_cpu_comm()
57 .write(|w| w.lp_trigger_hp().set_bit());
58}
59
60#[cfg(feature = "esp32c6")]
61global_asm!(
62 r#"
63 .section .init.vector, "ax"
64 /* This is the vector table. It is currently empty, but will be populated
65 * with exception and interrupt handlers when this is supported
66 */
67
68 .align 0x4, 0xff
69 .global _vector_table
70 .type _vector_table, @function
71_vector_table:
72 .option push
73 .option norvc
74
75 .rept 32
76 nop
77 .endr
78
79 .option pop
80 .size _vector_table, .-_vector_table
81
82 .section .init, "ax"
83 .global reset_vector
84
85/* The reset vector, jumps to startup code */
86reset_vector:
87 j __start
88
89__start:
90 /* setup the stack pointer */
91 la sp, __stack_top
92 call rust_main
93loop:
94 j loop
95"#
96);
97
98#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
99global_asm!(
100 r#"
101 .section .text.vectors
102 .global irq_vector
103 .global reset_vector
104
105/* The reset vector, jumps to startup code */
106reset_vector:
107 j __start
108
109/* Interrupt handler */
110.balign 16
111irq_vector:
112 ret
113
114 .section .text
115
116__start:
117 /* setup the stack pointer */
118 la sp, __stack_top
119
120 call ulp_riscv_rescue_from_monitor
121 call rust_main
122 call ulp_riscv_halt
123loop:
124 j loop
125"#
126);
127
128#[link_section = ".init.rust"]
129#[export_name = "rust_main"]
130unsafe extern "C" fn lp_core_startup() -> ! {
131 extern "Rust" {
132 fn main() -> !;
133 }
134
135 #[cfg(feature = "esp32c6")]
136 if (*pac::LP_CLKRST::PTR)
137 .lp_clk_conf()
138 .read()
139 .fast_clk_sel()
140 .bit_is_set()
141 {
142 CPU_CLOCK = XTAL_D2_CLK_HZ;
143 }
144
145 main();
146}
147
148#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
149#[link_section = ".init.rust"]
150#[no_mangle]
151unsafe extern "C" fn ulp_riscv_rescue_from_monitor() {
152 unsafe { &*pac::RTC_CNTL::PTR }
154 .cocpu_ctrl()
155 .modify(|_, w| w.cocpu_done().clear_bit().cocpu_shut_reset_en().clear_bit());
156}
157
158#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
159#[link_section = ".init.rust"]
160#[no_mangle]
161unsafe extern "C" fn ulp_riscv_halt() {
162 unsafe { &*pac::RTC_CNTL::PTR }
163 .cocpu_ctrl()
164 .modify(|_, w| unsafe { w.cocpu_shut_2_clk_dis().bits(0x3f).cocpu_done().set_bit() });
165
166 loop {
167 riscv::asm::wfi();
168 }
169}