Support ESP32S2
This commit is contained in:
parent
52f388e9a1
commit
9c5468e814
@ -17,7 +17,7 @@ paste = "1.0"
|
|||||||
riscv = { version = "0.7", optional = true }
|
riscv = { version = "0.7", optional = true }
|
||||||
void = { version = "1.0", default-features = false }
|
void = { version = "1.0", default-features = false }
|
||||||
xtensa-lx = { version = "0.6.0", optional = true }
|
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" }
|
procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" }
|
||||||
# IMPORTANT:
|
# IMPORTANT:
|
||||||
# Each supported device MUST have its PAC included below along with a
|
# 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]
|
[features]
|
||||||
esp32 = ["esp32_pac", "esp32_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "procmacros/rtc_slow", "dual_core"]
|
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"]
|
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
|
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/esp32", "procmacros/rtc_slow", "dual_core"] # FIXME
|
esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/esp32", "xtensa-lx-rt/esp32s3", "procmacros/rtc_slow", "dual_core"] # FIXME
|
||||||
|
|
||||||
single_core = []
|
single_core = []
|
||||||
dual_core = []
|
dual_core = []
|
||||||
|
|||||||
@ -11,7 +11,8 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enumeration of available CPU interrupts
|
/// 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)]
|
#[allow(unused)]
|
||||||
pub enum CpuInterrupt {
|
pub enum CpuInterrupt {
|
||||||
Interrupt0LevelPriority1 = 0,
|
Interrupt0LevelPriority1 = 0,
|
||||||
@ -30,7 +31,7 @@ pub enum CpuInterrupt {
|
|||||||
Interrupt13LevelPriority1,
|
Interrupt13LevelPriority1,
|
||||||
Interrupt14NmiPriority7,
|
Interrupt14NmiPriority7,
|
||||||
Interrupt15Timer1Priority3,
|
Interrupt15Timer1Priority3,
|
||||||
Interrupt16Timer2Priority3,
|
Interrupt16Timer2Priority5,
|
||||||
Interrupt17LevelPriority1,
|
Interrupt17LevelPriority1,
|
||||||
Interrupt18LevelPriority1,
|
Interrupt18LevelPriority1,
|
||||||
Interrupt19LevelPriority2,
|
Interrupt19LevelPriority2,
|
||||||
@ -53,13 +54,12 @@ pub fn enable(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let interrupt_number = interrupt as isize;
|
let interrupt_number = interrupt as isize;
|
||||||
let cpu_interrupt_number = which as isize;
|
let cpu_interrupt_number = which as isize;
|
||||||
let intr = &*crate::pac::DPORT::ptr();
|
|
||||||
let intr_map_base = match core {
|
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")]
|
#[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")]
|
#[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
|
intr_map_base
|
||||||
.offset(interrupt_number)
|
.offset(interrupt_number)
|
||||||
@ -71,13 +71,12 @@ pub fn enable(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
|
|||||||
pub fn disable(core: Cpu, interrupt: Interrupt) {
|
pub fn disable(core: Cpu, interrupt: Interrupt) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let interrupt_number = interrupt as isize;
|
let interrupt_number = interrupt as isize;
|
||||||
let intr = &*crate::pac::DPORT::ptr();
|
|
||||||
let intr_map_base = match core {
|
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")]
|
#[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")]
|
#[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);
|
intr_map_base.offset(interrupt_number).write_volatile(0);
|
||||||
}
|
}
|
||||||
@ -95,19 +94,84 @@ pub fn get_status(core: Cpu) -> u128 {
|
|||||||
unsafe {
|
unsafe {
|
||||||
match core {
|
match core {
|
||||||
Cpu::ProCpu => {
|
Cpu::ProCpu => {
|
||||||
((*crate::pac::DPORT::ptr()).pro_intr_status_0.read().bits() as u128)
|
((&*core0_interrupt_peripheral())
|
||||||
| ((*crate::pac::DPORT::ptr()).pro_intr_status_1.read().bits() as u128) << 32
|
.pro_intr_status_0
|
||||||
| ((*crate::pac::DPORT::ptr()).pro_intr_status_2.read().bits() as u128) << 64
|
.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 => {
|
Cpu::AppCpu => {
|
||||||
((*crate::pac::DPORT::ptr()).app_intr_status_0.read().bits() as u128)
|
((&*core1_interrupt_peripheral())
|
||||||
| ((*crate::pac::DPORT::ptr()).app_intr_status_1.read().bits() as u128) << 32
|
.app_intr_status_0
|
||||||
| ((*crate::pac::DPORT::ptr()).app_intr_status_2.read().bits() as u128) << 64
|
.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 => {
|
||||||
|
((&*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)]
|
#[xtensa_lx_rt::interrupt(1)]
|
||||||
fn _level1_interrupt() {
|
fn _level1_interrupt() {
|
||||||
unsafe { level1_interrupt() };
|
unsafe { level1_interrupt() };
|
||||||
|
|||||||
@ -30,6 +30,8 @@ pub use esp32s3_pac as pac;
|
|||||||
pub mod delay;
|
pub mod delay;
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
#[cfg_attr(feature = "esp32", path = "interrupt/xtensa.rs")]
|
#[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")]
|
#[cfg_attr(feature = "esp32c3", path = "interrupt/riscv.rs")]
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|||||||
@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] }
|
|||||||
nb = "1.0"
|
nb = "1.0"
|
||||||
void = { version = "1.0", default-features = false }
|
void = { version = "1.0", default-features = false }
|
||||||
xtensa-lx = { version = "0.6.0", features = ["esp32"] }
|
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]
|
[dependencies.esp-hal-common]
|
||||||
path = "../esp-hal-common"
|
path = "../esp-hal-common"
|
||||||
|
|||||||
@ -33,6 +33,9 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
static mut _stack_end_cpu0: 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
|
// copying data from flash to various data segments is done by the bootloader
|
||||||
// initialization to zero needs to be done by the application
|
// 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_fast_bss_start, &mut _rtc_fast_bss_end);
|
||||||
xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_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
|
// continue with default reset handler
|
||||||
xtensa_lx_rt::Reset();
|
xtensa_lx_rt::Reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] }
|
|||||||
nb = "1.0"
|
nb = "1.0"
|
||||||
void = { version = "1.0", default-features = false }
|
void = { version = "1.0", default-features = false }
|
||||||
xtensa-lx = { version = "0.6.0", features = ["esp32"] } # FIXME
|
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]
|
[dependencies.esp-hal-common]
|
||||||
path = "../esp-hal-common"
|
path = "../esp-hal-common"
|
||||||
|
|||||||
@ -13,6 +13,13 @@ fn main() {
|
|||||||
.write_all(include_bytes!("rom.x"))
|
.write_all(include_bytes!("rom.x"))
|
||||||
.unwrap();
|
.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());
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
|
||||||
// Only re-run the build script when memory.x is changed,
|
// Only re-run the build script when memory.x is changed,
|
||||||
|
|||||||
27
esp32s2-hal/examples/hello_world.rs
Normal file
27
esp32s2-hal/examples/hello_world.rs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
91
esp32s2-hal/examples/ram.rs
Normal file
91
esp32s2-hal/examples/ram.rs
Normal file
@ -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<UART0>) {
|
||||||
|
writeln!(serial0, "Hello world!").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ram(rtc_fast)]
|
||||||
|
fn function_in_rtc_ram() -> u32 {
|
||||||
|
42
|
||||||
|
}
|
||||||
7
esp32s2-hal/hal-defaults.x
Normal file
7
esp32s2-hal/hal-defaults.x
Normal file
@ -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);
|
||||||
@ -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"
|
||||||
@ -1,7 +1,58 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub use embedded_hal as ehal;
|
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]
|
#[no_mangle]
|
||||||
extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {}
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] }
|
|||||||
nb = "1.0"
|
nb = "1.0"
|
||||||
void = { version = "1.0", default-features = false }
|
void = { version = "1.0", default-features = false }
|
||||||
xtensa-lx = { version = "0.6.0", features = ["esp32"] } # FIXME
|
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]
|
[dependencies.esp-hal-common]
|
||||||
path = "../esp-hal-common"
|
path = "../esp-hal-common"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user