1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! `no_std` HAL for the ESP32-S2 from Espressif.
//!
//! Implements a number of the traits defined by the various packages in the
//! [embedded-hal] repository.
//!
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal
#![no_std]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
use esp_hal_common::xtensa_lx_rt::exception::ExceptionCause;
pub use esp_hal_common::*;
// Always enable atomic emulation on ESP32-S2
use xtensa_atomic_emulation_trap as _;
/// Common module for analog functions
pub mod analog {
pub use esp_hal_common::analog::{AvailableAnalog, SensExt};
}
/// Function initializes ESP32 specific memories (RTC slow and fast) and
/// then calls original Reset function
///
/// ENTRY point is defined in memory.x
/// *Note: the pre_init function is called in the original reset handler
/// after the initializations done in this function*
#[cfg(feature = "rt")]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn ESP32Reset() -> ! {
// These symbols come from `memory.x`
extern "C" {
static mut _rtc_fast_bss_start: u32;
static mut _rtc_fast_bss_end: u32;
static mut _rtc_slow_bss_start: u32;
static mut _rtc_slow_bss_end: u32;
static mut _stack_end_cpu0: u32;
}
// set stack pointer to end of memory: no need to retain stack up to this point
esp_hal_common::xtensa_lx::set_stack_pointer(&mut _stack_end_cpu0);
// copying data from flash to various data segments is done by the bootloader
// initialization to zero needs to be done by the application
// Initialize RTC RAM
esp_hal_common::xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end);
esp_hal_common::xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end);
// continue with default reset handler
esp_hal_common::xtensa_lx_rt::Reset();
}
/// The ESP32 has a first stage bootloader that handles loading program data
/// into the right place therefore we skip loading it again.
#[doc(hidden)]
#[no_mangle]
#[rustfmt::skip]
pub extern "Rust" fn __init_data() -> bool {
false
}
/// Atomic Emulation is always enabled on ESP32-S2
#[doc(hidden)]
#[no_mangle]
#[export_name = "__exception"] // this overrides the exception handler in xtensa_lx_rt
#[link_section = ".rwtext"]
unsafe fn exception(cause: ExceptionCause, save_frame: &mut trapframe::TrapFrame) {
if let ExceptionCause::Illegal = cause {
let mut regs = [
save_frame.A0,
save_frame.A1,
save_frame.A2,
save_frame.A3,
save_frame.A4,
save_frame.A5,
save_frame.A6,
save_frame.A7,
save_frame.A8,
save_frame.A9,
save_frame.A10,
save_frame.A11,
save_frame.A12,
save_frame.A13,
save_frame.A14,
save_frame.A15,
];
if xtensa_atomic_emulation_trap::atomic_emulation(save_frame.PC, &mut regs) {
save_frame.PC += 3; // 24bit instruction
save_frame.A0 = regs[0];
save_frame.A1 = regs[1];
save_frame.A2 = regs[2];
save_frame.A3 = regs[3];
save_frame.A4 = regs[4];
save_frame.A5 = regs[5];
save_frame.A6 = regs[6];
save_frame.A7 = regs[7];
save_frame.A8 = regs[8];
save_frame.A9 = regs[9];
save_frame.A10 = regs[10];
save_frame.A11 = regs[11];
save_frame.A12 = regs[12];
save_frame.A13 = regs[13];
save_frame.A14 = regs[14];
save_frame.A15 = regs[15];
return;
}
}
extern "C" {
fn __user_exception(cause: ExceptionCause, save_frame: &mut trapframe::TrapFrame);
}
__user_exception(cause, save_frame);
}