Skip to content

Commit

Permalink
Support ESP32S2
Browse files Browse the repository at this point in the history
  • Loading branch information
bjoernQ authored and jessebraham committed Feb 14, 2022
1 parent 52f388e commit 9c5468e
Show file tree
Hide file tree
Showing 13 changed files with 445 additions and 26 deletions.
6 changes: 3 additions & 3 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 = []
96 changes: 80 additions & 16 deletions esp-hal-common/src/interrupt/xtensa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -30,7 +31,7 @@ pub enum CpuInterrupt {
Interrupt13LevelPriority1,
Interrupt14NmiPriority7,
Interrupt15Timer1Priority3,
Interrupt16Timer2Priority3,
Interrupt16Timer2Priority5,
Interrupt17LevelPriority1,
Interrupt18LevelPriority1,
Interrupt19LevelPriority2,
Expand All @@ -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)
Expand All @@ -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);
}
Expand All @@ -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() };
Expand Down
2 changes: 2 additions & 0 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion esp32-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 3 additions & 3 deletions esp32-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ 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

// 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);

// 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();
}
Expand Down
2 changes: 1 addition & 1 deletion esp32s2-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 7 additions & 0 deletions esp32s2-hal/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
27 changes: 27 additions & 0 deletions esp32s2-hal/examples/hello_world.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 91 additions & 0 deletions esp32s2-hal/examples/ram.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions esp32s2-hal/hal-defaults.x
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit 9c5468e

Please sign in to comment.