diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index b760f08a74c..54f0679862f 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -17,7 +17,7 @@ paste = "1.0" riscv = { version = "0.7", optional = true } void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.6.0", optional = true } -xtensa-lx-rt = { version = "0.8.0", features = ["esp32"], optional = true } +xtensa-lx-rt = { version = "0.9.0", optional = true } procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" } # IMPORTANT: # Each supported device MUST have its PAC included below along with a @@ -30,8 +30,8 @@ esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.g [features] esp32 = ["esp32_pac", "esp32_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "procmacros/rtc_slow", "dual_core"] esp32c3 = ["esp32c3_pac", "esp32c3_pac/rt", "riscv", "single_core"] -esp32s2 = ["esp32s2_pac", "esp32s2_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "procmacros/rtc_slow", "single_core"] # FIXME -esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "procmacros/rtc_slow", "dual_core"] # FIXME +esp32s2 = ["esp32s2_pac", "esp32s2_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32s2", "procmacros/rtc_slow", "single_core"] # FIXME +esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32s3", "procmacros/rtc_slow", "dual_core"] # FIXME single_core = [] dual_core = [] diff --git a/esp-hal-common/src/interrupt/xtensa.rs b/esp-hal-common/src/interrupt/xtensa.rs index 9d02c376d6c..eba47acb9c6 100644 --- a/esp-hal-common/src/interrupt/xtensa.rs +++ b/esp-hal-common/src/interrupt/xtensa.rs @@ -11,7 +11,8 @@ extern "C" { } /// Enumeration of available CPU interrupts -/// It's possible to create one handler per priority level. (e.g `level1_interrupt`) +/// It's possible to create one handler per priority level. (e.g +/// `level1_interrupt`) #[allow(unused)] pub enum CpuInterrupt { Interrupt0LevelPriority1 = 0, @@ -30,7 +31,7 @@ pub enum CpuInterrupt { Interrupt13LevelPriority1, Interrupt14NmiPriority7, Interrupt15Timer1Priority3, - Interrupt16Timer2Priority3, + Interrupt16Timer2Priority5, Interrupt17LevelPriority1, Interrupt18LevelPriority1, Interrupt19LevelPriority2, @@ -53,13 +54,12 @@ pub fn enable(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { unsafe { let interrupt_number = interrupt as isize; let cpu_interrupt_number = which as isize; - let intr = &*crate::pac::DPORT::ptr(); let intr_map_base = match core { - Cpu::ProCpu => intr.pro_mac_intr_map.as_ptr(), + Cpu::ProCpu => (&*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), #[cfg(feature = "dual_core")] - Cpu::AppCpu => intr.app_mac_intr_map.as_ptr(), + Cpu::AppCpu => (&*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), #[cfg(feature = "single_core")] - Cpu::AppCpu => intr.pro_mac_intr_map.as_ptr(), + Cpu::AppCpu => (&*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), }; intr_map_base .offset(interrupt_number) @@ -71,13 +71,12 @@ pub fn enable(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { pub fn disable(core: Cpu, interrupt: Interrupt) { unsafe { let interrupt_number = interrupt as isize; - let intr = &*crate::pac::DPORT::ptr(); let intr_map_base = match core { - Cpu::ProCpu => intr.pro_mac_intr_map.as_ptr(), + Cpu::ProCpu => (&*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), #[cfg(feature = "dual_core")] - Cpu::AppCpu => intr.app_mac_intr_map.as_ptr(), + Cpu::AppCpu => (&*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), #[cfg(feature = "single_core")] - Cpu::AppCpu => intr.pro_mac_intr_map.as_ptr(), + Cpu::AppCpu => (&*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), }; intr_map_base.offset(interrupt_number).write_volatile(0); } @@ -95,19 +94,84 @@ pub fn get_status(core: Cpu) -> u128 { unsafe { match core { Cpu::ProCpu => { - ((*crate::pac::DPORT::ptr()).pro_intr_status_0.read().bits() as u128) - | ((*crate::pac::DPORT::ptr()).pro_intr_status_1.read().bits() as u128) << 32 - | ((*crate::pac::DPORT::ptr()).pro_intr_status_2.read().bits() as u128) << 64 + ((&*core0_interrupt_peripheral()) + .pro_intr_status_0 + .read() + .bits() as u128) + | ((&*core0_interrupt_peripheral()) + .pro_intr_status_1 + .read() + .bits() as u128) + << 32 + | ((&*core0_interrupt_peripheral()) + .pro_intr_status_2 + .read() + .bits() as u128) + << 64 } + #[cfg(feature = "dual_core")] + Cpu::AppCpu => { + ((&*core1_interrupt_peripheral()) + .app_intr_status_0 + .read() + .bits() as u128) + | ((&*core1_interrupt_peripheral()) + .app_intr_status_1 + .read() + .bits() as u128) + << 32 + | ((&*core1_interrupt_peripheral()) + .app_intr_status_2 + .read() + .bits() as u128) + << 64 + } + #[cfg(feature = "single_core")] Cpu::AppCpu => { - ((*crate::pac::DPORT::ptr()).app_intr_status_0.read().bits() as u128) - | ((*crate::pac::DPORT::ptr()).app_intr_status_1.read().bits() as u128) << 32 - | ((*crate::pac::DPORT::ptr()).app_intr_status_2.read().bits() as u128) << 64 + ((&*core0_interrupt_peripheral()) + .pro_intr_status_0 + .read() + .bits() as u128) + | ((&*core0_interrupt_peripheral()) + .pro_intr_status_1 + .read() + .bits() as u128) + << 32 + | ((&*core0_interrupt_peripheral()) + .pro_intr_status_2 + .read() + .bits() as u128) + << 64 } } } } +#[cfg(feature = "esp32")] +unsafe fn core0_interrupt_peripheral() -> *const crate::pac::dport::RegisterBlock { + crate::pac::DPORT::ptr() +} + +#[cfg(feature = "esp32")] +unsafe fn core1_interrupt_peripheral() -> *const crate::pac::dport::RegisterBlock { + crate::pac::DPORT::ptr() +} + +#[cfg(feature = "esp32s2")] +unsafe fn core0_interrupt_peripheral() -> *const crate::pac::interrupt::RegisterBlock { + crate::pac::INTERRUPT::ptr() +} + +#[cfg(feature = "esp32s3")] +unsafe fn core0_interrupt_peripheral() -> *const crate::pac::interrupt_core0::RegisterBlock { + crate::pac::INTERRUPT_CORE0::ptr() +} + +#[cfg(feature = "esp32s3")] +unsafe fn core1_interrupt_peripheral() -> *const crate::pac::interrupt_core1::RegisterBlock { + crate::pac::INTERRUPT_CORE1::ptr() +} + #[xtensa_lx_rt::interrupt(1)] fn _level1_interrupt() { unsafe { level1_interrupt() }; diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 6a10207d214..45881966acd 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -30,6 +30,8 @@ pub use esp32s3_pac as pac; pub mod delay; pub mod gpio; #[cfg_attr(feature = "esp32", path = "interrupt/xtensa.rs")] +#[cfg_attr(feature = "esp32s2", path = "interrupt/xtensa.rs")] +#[cfg_attr(feature = "esp32s3", path = "interrupt/xtensa.rs")] #[cfg_attr(feature = "esp32c3", path = "interrupt/riscv.rs")] pub mod interrupt; pub mod prelude; diff --git a/esp32-hal/Cargo.toml b/esp32-hal/Cargo.toml index e74701d5a39..fed540f6149 100644 --- a/esp32-hal/Cargo.toml +++ b/esp32-hal/Cargo.toml @@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] } nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.6.0", features = ["esp32"] } -xtensa-lx-rt = { version = "0.8.0", features = ["esp32"], optional = true } +xtensa-lx-rt = { version = "0.9.0", features = ["esp32"], optional = true } [dependencies.esp-hal-common] path = "../esp-hal-common" diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index d2564bc22fd..80d72f81877 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -33,6 +33,9 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { static mut _stack_end_cpu0: u32; } + // set stack pointer to end of memory: no need to retain stack up to this point + 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 @@ -40,9 +43,6 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end); - // set stack pointer to end of memory: no need to retain stack up to this point - xtensa_lx::set_stack_pointer(&mut _stack_end_cpu0); - // continue with default reset handler xtensa_lx_rt::Reset(); } diff --git a/esp32s2-hal/Cargo.toml b/esp32s2-hal/Cargo.toml index 0223f40e7e5..ba30245edbe 100644 --- a/esp32s2-hal/Cargo.toml +++ b/esp32s2-hal/Cargo.toml @@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] } nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.6.0", features = ["esp32"] } # FIXME -xtensa-lx-rt = { version = "0.8.0", features = ["esp32"], optional = true } +xtensa-lx-rt = { version = "0.9.0", features = ["esp32s2"], optional = true } [dependencies.esp-hal-common] path = "../esp-hal-common" diff --git a/esp32s2-hal/build.rs b/esp32s2-hal/build.rs index bd5affeecdf..ef0b853979f 100644 --- a/esp32s2-hal/build.rs +++ b/esp32s2-hal/build.rs @@ -13,6 +13,13 @@ fn main() { .write_all(include_bytes!("rom.x")) .unwrap(); + File::create(out.join("hal-defaults.x")) + .unwrap() + .write_all(include_bytes!("hal-defaults.x")) + .unwrap(); + + println!("cargo:rustc-link-arg=-Thal-defaults.x"); + println!("cargo:rustc-link-search={}", out.display()); // Only re-run the build script when memory.x is changed, diff --git a/esp32s2-hal/examples/hello_world.rs b/esp32s2-hal/examples/hello_world.rs new file mode 100644 index 00000000000..2b8882cc417 --- /dev/null +++ b/esp32s2-hal/examples/hello_world.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] + +use core::fmt::Write; + +use esp32s2_hal::{pac::Peripherals, prelude::*, Serial, Timer}; +use nb::block; +use panic_halt as _; +use xtensa_lx_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + + let mut timer0 = Timer::new(peripherals.TIMG0); + let mut serial0 = Serial::new(peripherals.UART0).unwrap(); + + // Disable watchdog timer + timer0.disable(); + + timer0.start(40_000_000u64); + + loop { + writeln!(serial0, "Hello world!").unwrap(); + block!(timer0.wait()).unwrap(); + } +} diff --git a/esp32s2-hal/examples/ram.rs b/esp32s2-hal/examples/ram.rs new file mode 100644 index 00000000000..782ddfea1a4 --- /dev/null +++ b/esp32s2-hal/examples/ram.rs @@ -0,0 +1,91 @@ +#![no_std] +#![no_main] + +use core::fmt::Write; + +use esp32s2_hal::{ + pac::{Peripherals, UART0}, + prelude::*, + ram, + Serial, + Timer, +}; +use nb::block; +use panic_halt as _; +use xtensa_lx_rt::entry; + +#[ram(rtc_fast)] +static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb]; + +#[ram(rtc_fast, uninitialized)] +static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2]; + +#[ram(rtc_fast, zeroed)] +static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8]; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + + let mut timer0 = Timer::new(peripherals.TIMG0); + let mut serial0 = Serial::new(peripherals.UART0).unwrap(); + + // Disable watchdog timer + timer0.disable(); + + timer0.start(10_000_000u64); + + writeln!( + serial0, + "IRAM function located at {:p}", + function_in_ram as *const () + ) + .unwrap(); + unsafe { + writeln!(serial0, "SOME_INITED_DATA {:x?}", SOME_INITED_DATA).unwrap(); + writeln!(serial0, "SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA).unwrap(); + writeln!(serial0, "SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA).unwrap(); + + SOME_INITED_DATA[0] = 0xff; + SOME_ZEROED_DATA[0] = 0xff; + + writeln!(serial0, "SOME_INITED_DATA {:x?}", SOME_INITED_DATA).unwrap(); + writeln!(serial0, "SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA).unwrap(); + writeln!(serial0, "SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA).unwrap(); + + if SOME_UNINITED_DATA[0] != 0 { + SOME_UNINITED_DATA[0] = 0; + SOME_UNINITED_DATA[1] = 0; + } + + if SOME_UNINITED_DATA[1] == 0xff { + SOME_UNINITED_DATA[1] = 0; + } + + writeln!(serial0, "Counter {}", SOME_UNINITED_DATA[1]).unwrap(); + SOME_UNINITED_DATA[1] += 1; + } + + writeln!( + serial0, + "RTC_FAST function located at {:p}", + function_in_rtc_ram as *const () + ) + .unwrap(); + writeln!(serial0, "Result {}", function_in_rtc_ram()).unwrap(); + + loop { + function_in_ram(&mut serial0); + block!(timer0.wait()).unwrap(); + } +} + +#[ram] +fn function_in_ram(serial0: &mut Serial) { + writeln!(serial0, "Hello world!").unwrap(); +} + +#[ram(rtc_fast)] +fn function_in_rtc_ram() -> u32 { + 42 +} diff --git a/esp32s2-hal/hal-defaults.x b/esp32s2-hal/hal-defaults.x new file mode 100644 index 00000000000..f58999823fc --- /dev/null +++ b/esp32s2-hal/hal-defaults.x @@ -0,0 +1,7 @@ +PROVIDE(level1_interrupt = DefaultHandler); +PROVIDE(level2_interrupt = DefaultHandler); +PROVIDE(level3_interrupt = DefaultHandler); +PROVIDE(level4_interrupt = DefaultHandler); +PROVIDE(level5_interrupt = DefaultHandler); +PROVIDE(level6_interrupt = DefaultHandler); +PROVIDE(level7_interrupt = DefaultHandler); diff --git a/esp32s2-hal/memory.x b/esp32s2-hal/memory.x index e69de29bb2d..f3927281d9c 100644 --- a/esp32s2-hal/memory.x +++ b/esp32s2-hal/memory.x @@ -0,0 +1,170 @@ +/* This memory map assumes the flash cache is on; + the blocks used are excluded from the various memory ranges + + see: https://github.com/espressif/esp-idf/blob/master/components/soc/src/esp32/soc_memory_layout.c + for details + */ + +/* override entry point */ +ENTRY(ESP32Reset) + +/* reserved at the start of DRAM */ +RESERVE_DRAM = 0x4000; + +/* reserved at the start of the RTC memories for use by the ULP processor */ +RESERVE_RTC_FAST = 0; +RESERVE_RTC_SLOW = 0; + +/* define stack size for both cores */ +STACK_SIZE = 8k; + +/* Specify main memory areas */ +MEMORY +{ + vectors_seg ( RX ) : ORIGIN = 0x40022000, len = 1k /* SRAM0 */ + iram_seg ( RX ) : ORIGIN = 0x40022400, len = 128k-0x400 /* SRAM0 */ + + dram_seg ( RW ) : ORIGIN = 0x3FFB0000 + RESERVE_DRAM, len = 176k - RESERVE_DRAM + reserved_for_boot_seg : ORIGIN = 0x3FFDC200, len = 144k /* SRAM1; reserved for static ROM usage; can be used for heap */ + + /* external flash + The 0x20 offset is a convenience for the app binary image generation. + Flash cache has 64KB pages. The .bin file which is flashed to the chip + has a 0x18 byte file header, and each segment has a 0x08 byte segment + header. Setting this offset makes it simple to meet the flash cache MMU's + constraint that (paddr % 64KB == vaddr % 64KB).) + */ + irom_seg ( RX ) : ORIGIN = 0x40080020, len = 3M - 0x20 + drom_seg ( R ) : ORIGIN = 0x3F000020, len = 4M - 0x20 + + + /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ + rtc_fast_iram_seg(RWX) : ORIGIN = 0x40070000, len = 8k + + /* RTC fast memory (same block as above), viewed from data bus. Only for core 0 (PRO_CPU) */ + rtc_fast_dram_seg(RW) : ORIGIN = 0x3ff9e000 + RESERVE_RTC_FAST, len = 8k - RESERVE_RTC_FAST + + /* RTC slow memory (data accessible). Persists over deep sleep. */ + rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW + + /* external memory, including data and text */ + psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000 +} + +/* map generic regions to output sections */ +INCLUDE "alias.x" + +/* esp32 specific regions */ +SECTIONS { + .rtc_fast.text : { + . = ALIGN(4); + *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) + } > rtc_fast_iram_seg AT > RODATA + + /* + This section is required to skip rtc.text area because rtc_iram_seg and + rtc_data_seg are reflect the same address space on different buses. + */ + .rtc_fast.dummy (NOLOAD) : + { + _rtc_dummy_start = ABSOLUTE(.); /* needed to make section proper size */ + . = SIZEOF(.rtc_fast.text); + _rtc_dummy_end = ABSOLUTE(.); /* needed to make section proper size */ + } > rtc_fast_dram_seg + + + .rtc_fast.data : + { + . = ALIGN(4); + _rtc_fast_data_start = ABSOLUTE(.); + *(.rtc_fast.data .rtc_fast.data.*) + _rtc_fast_data_end = ABSOLUTE(.); + } > rtc_fast_dram_seg AT > RODATA + + .rtc_fast.bss (NOLOAD) : + { + . = ALIGN(4); + _rtc_fast_bss_start = ABSOLUTE(.); + *(.rtc_fast.bss .rtc_fast.bss.*) + _rtc_fast_bss_end = ABSOLUTE(.); + } > rtc_fast_dram_seg + + .rtc_fast.noinit (NOLOAD) : + { + . = ALIGN(4); + *(.rtc_fast.noinit .rtc_fast.noinit.*) + } > rtc_fast_dram_seg + + + .rtc_slow.text : { + . = ALIGN(4); + *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) + } > rtc_slow_seg AT > RODATA + + .rtc_slow.data : + { + . = ALIGN(4); + _rtc_slow_data_start = ABSOLUTE(.); + *(.rtc_slow.data .rtc_slow.data.*) + _rtc_slow_data_end = ABSOLUTE(.); + } > rtc_slow_seg AT > RODATA + + .rtc_slow.bss (NOLOAD) : + { + . = ALIGN(4); + _rtc_slow_bss_start = ABSOLUTE(.); + *(.rtc_slow.bss .rtc_slow.bss.*) + _rtc_slow_bss_end = ABSOLUTE(.); + } > rtc_slow_seg + + .rtc_slow.noinit (NOLOAD) : + { + . = ALIGN(4); + *(.rtc_slow.noinit .rtc_slow.noinit.*) + } > rtc_slow_seg + + .external.data : + { + _external_data_start = ABSOLUTE(.); + . = ALIGN(4); + *(.external.data .external.data.*) + _external_data_end = ABSOLUTE(.); + } > psram_seg AT > RODATA + + .external.bss (NOLOAD) : + { + _external_bss_start = ABSOLUTE(.); + . = ALIGN(4); + *(.external.bss .external.bss.*) + _external_bss_end = ABSOLUTE(.); + } > psram_seg + + .external.noinit (NOLOAD) : + { + . = ALIGN(4); + *(.external.noinit .external.noinit.*) + } > psram_seg + + /* must be last segment using psram_seg */ + .external_heap_start (NOLOAD) : + { + . = ALIGN (4); + _external_heap_start = ABSOLUTE(.); + } > psram_seg +} + +_external_ram_start = ABSOLUTE(ORIGIN(psram_seg)); +_external_ram_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg)); + +_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg)+LENGTH(reserved_for_boot_seg) - 2*STACK_SIZE; +_text_heap_end = ABSOLUTE(ORIGIN(iram_seg)+LENGTH(iram_seg)); +_external_heap_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg)); + +_stack_start_cpu1 = _heap_end; +_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE; +_stack_start_cpu0 = _stack_end_cpu1; +_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE; + +EXTERN(DefaultHandler); + +INCLUDE "device.x" diff --git a/esp32s2-hal/src/lib.rs b/esp32s2-hal/src/lib.rs index 0ad0b5e3bba..44fe037d922 100644 --- a/esp32s2-hal/src/lib.rs +++ b/esp32s2-hal/src/lib.rs @@ -1,7 +1,58 @@ #![no_std] pub use embedded_hal as ehal; -pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer}; +pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer, ram}; #[no_mangle] extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} + +/// 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 + 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 + xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); + xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end); + + // continue with default reset handler + 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 +} + +fn _gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 { + int_enable as u8 + | ((nmi_enable as u8) << 1) + | (int_enable as u8) << 2 + | ((nmi_enable as u8) << 3) +} diff --git a/esp32s3-hal/Cargo.toml b/esp32s3-hal/Cargo.toml index eb7e51bd647..539e139541d 100644 --- a/esp32s3-hal/Cargo.toml +++ b/esp32s3-hal/Cargo.toml @@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] } nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.6.0", features = ["esp32"] } # FIXME -xtensa-lx-rt = { version = "0.8.0", features = ["esp32"], optional = true } +xtensa-lx-rt = { version = "0.9.0", features = ["esp32s3"], optional = true } [dependencies.esp-hal-common] path = "../esp-hal-common"