diff --git a/esp-hal-common/src/delay.rs b/esp-hal-common/src/delay.rs index 4de38e7a481..f0134e2303d 100644 --- a/esp-hal-common/src/delay.rs +++ b/esp-hal-common/src/delay.rs @@ -32,60 +32,33 @@ where mod delay { use fugit::HertzU64; - use crate::{clock::Clocks, pac::SYSTIMER}; + use crate::{clock::Clocks, systimer::SystemTimer}; /// Uses the `SYSTIMER` peripheral for counting clock cycles, as /// unfortunately the ESP32-C3 does NOT implement the `mcycle` CSR, which is /// how we would normally do this. pub struct Delay { - systimer: SYSTIMER, freq: HertzU64, } impl Delay { /// Create a new Delay instance - pub fn new(systimer: SYSTIMER, clocks: &Clocks) -> Self { + pub fn new(clocks: &Clocks) -> Self { // The counters and comparators are driven using `XTAL_CLK`. The average clock // frequency is fXTAL_CLK/2.5, which is 16 MHz. The timer counting is // incremented by 1/16 μs on each `CNT_CLK` cycle. Self { - systimer, freq: HertzU64::MHz((clocks.xtal_clock.to_MHz() * 10 / 25) as u64), } } - /// Return the raw interface to the underlying SYSTIMER instance - pub fn free(self) -> SYSTIMER { - self.systimer - } - /// Delay for the specified number of microseconds pub fn delay(&self, us: u32) { - let t0 = self.unit0_value(); + let t0 = SystemTimer::now(); let clocks = (us as u64 * self.freq.raw()) / HertzU64::MHz(1).raw(); - while self.unit0_value().wrapping_sub(t0) <= clocks {} - } - - #[inline(always)] - fn unit0_value(&self) -> u64 { - self.systimer - .unit0_op - .write(|w| w.timer_unit0_update().set_bit()); - - while !self - .systimer - .unit0_op - .read() - .timer_unit0_value_valid() - .bit_is_set() - {} - - let value_lo = self.systimer.unit0_value_lo.read().bits(); - let value_hi = self.systimer.unit0_value_hi.read().bits(); - - ((value_hi as u64) << 32) | value_lo as u64 + while SystemTimer::now().wrapping_sub(t0) <= clocks {} } } } diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 78315bbe32a..0ffb2ccc807 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -58,6 +58,8 @@ pub use spi::Spi; pub use timer::Timer; #[cfg(any(feature = "esp32c3", feature = "esp32s3"))] pub use usb_serial_jtag::UsbSerialJtag; +#[cfg(any(feature = "esp32c3", feature = "esp32s3", feature = "esp32s2"))] +pub mod systimer; pub mod clock; pub mod system; diff --git a/esp-hal-common/src/systimer.rs b/esp-hal-common/src/systimer.rs new file mode 100644 index 00000000000..913d4657fc7 --- /dev/null +++ b/esp-hal-common/src/systimer.rs @@ -0,0 +1,175 @@ +use core::{intrinsics::transmute, marker::PhantomData}; + +use crate::pac::{ + generic::Reg, + systimer::{ + target0_conf::TARGET0_CONF_SPEC, + target0_hi::TARGET0_HI_SPEC, + target0_lo::TARGET0_LO_SPEC, + }, + SYSTIMER, +}; + +// TODO this only handles unit0 of the systimer + +#[derive(Debug)] +pub struct SystemTimer { + _inner: SYSTIMER, + pub alarm0: Alarm, + pub alarm1: Alarm, + pub alarm2: Alarm, +} + +impl SystemTimer { + pub fn new(p: SYSTIMER) -> Self { + Self { + _inner: p, + alarm0: Alarm::new(), + alarm1: Alarm::new(), + alarm2: Alarm::new(), + } + } + + // TODO use fugit types + pub fn now() -> u64 { + // This should be safe to access from multiple contexts + // worst case scenario the second accesor ends up reading + // an older time stamp + let systimer = unsafe { &*SYSTIMER::ptr() }; + systimer + .unit0_op + .modify(|_, w| w.timer_unit0_update().set_bit()); + + while !systimer + .unit0_op + .read() + .timer_unit0_value_valid() + .bit_is_set() + {} + + let value_lo = systimer.unit0_value_lo.read().bits(); + let value_hi = systimer.unit0_value_hi.read().bits(); + + ((value_hi as u64) << 32) | value_lo as u64 + } +} + +#[derive(Debug)] +pub struct Target; +// pub struct Periodic; // TODO, also impl e-h timer traits + +#[derive(Debug)] +pub struct Alarm { + _pd: PhantomData, +} + +impl Alarm { + // private constructor + fn new() -> Self { + Self { _pd: PhantomData } + } + + pub fn enable_interrupt(&self) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + match CHANNEL { + 0 => systimer + .int_ena + .modify(|_, w| w.target0_int_ena().set_bit()), + 1 => systimer + .int_ena + .modify(|_, w| w.target1_int_ena().set_bit()), + 2 => systimer + .int_ena + .modify(|_, w| w.target2_int_ena().set_bit()), + _ => unreachable!(), + } + } + + pub fn clear_interrupt(&self) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + match CHANNEL { + 0 => systimer.int_clr.write(|w| w.target0_int_clr().set_bit()), + 1 => systimer.int_clr.write(|w| w.target1_int_clr().set_bit()), + 2 => systimer.int_clr.write(|w| w.target2_int_clr().set_bit()), + _ => unreachable!(), + } + } +} + +impl Alarm { + pub fn set_target(&self, timestamp: u64) { + unsafe { + let systimer = &*SYSTIMER::ptr(); + let (tconf, hi, lo): ( + &Reg, + &Reg, + &Reg, + ) = match CHANNEL { + 0 => ( + &systimer.target0_conf, + &systimer.target0_hi, + &systimer.target0_lo, + ), + 1 => ( + transmute(&systimer.target1_conf), + transmute(&systimer.target1_hi), + transmute(&systimer.target1_lo), + ), + 2 => ( + transmute(&systimer.target2_conf), + transmute(&systimer.target2_hi), + transmute(&systimer.target2_lo), + ), + _ => unreachable!(), + }; + + #[cfg(feature = "esp32s2")] + systimer.step.write(|w| w.timer_xtal_step().bits(0x1)); // run at XTAL freq, not 80 * XTAL freq + + #[cfg(any(feature = "esp32c3", feature = "esp32s3"))] + { + tconf.write(|w| w.target0_timer_unit_sel().clear_bit()); // default, use unit 0 + systimer + .conf + .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit()); + } + + tconf.write(|w| w.target0_period_mode().clear_bit()); // target mode + hi.write(|w| w.timer_target0_hi().bits((timestamp >> 32) as u32)); + lo.write(|w| w.timer_target0_lo().bits((timestamp & 0xFFFF_FFFF) as u32)); + + #[cfg(any(feature = "esp32c3", feature = "esp32s3"))] + { + match CHANNEL { + 0 => { + systimer + .comp0_load + .write(|w| w.timer_comp0_load().set_bit()); + } + 1 => systimer + .comp1_load + .write(|w| w.timer_comp1_load().set_bit()), + 2 => systimer + .comp2_load + .write(|w| w.timer_comp2_load().set_bit()), + _ => unreachable!(), + } + + systimer.conf.modify(|_r, w| match CHANNEL { + 0 => w.target0_work_en().set_bit(), + 1 => w.target1_work_en().set_bit(), + 2 => w.target2_work_en().set_bit(), + _ => unreachable!(), + }); + } + + #[cfg(feature = "esp32s2")] + tconf.modify(|_r, w| match CHANNEL { + 0 => w.target0_work_en().set_bit(), + 1 => w.target0_work_en().set_bit(), + 2 => w.target0_work_en().set_bit(), + _ => unreachable!(), + }); + } + } +} diff --git a/esp32c3-hal/examples/blinky.rs b/esp32c3-hal/examples/blinky.rs index 903aba0192f..0587c343b3f 100644 --- a/esp32c3-hal/examples/blinky.rs +++ b/esp32c3-hal/examples/blinky.rs @@ -39,7 +39,7 @@ fn main() -> ! { // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. - let mut delay = Delay::new(peripherals.SYSTIMER, &clocks); + let mut delay = Delay::new(&clocks); loop { led.toggle().unwrap(); diff --git a/esp32c3-hal/examples/gpio_interrupt.rs b/esp32c3-hal/examples/gpio_interrupt.rs index e598698367c..7ee585e6d18 100644 --- a/esp32c3-hal/examples/gpio_interrupt.rs +++ b/esp32c3-hal/examples/gpio_interrupt.rs @@ -79,7 +79,7 @@ fn main() -> ! { riscv::interrupt::enable(); } - let mut delay = Delay::new(peripherals.SYSTIMER, &clocks); + let mut delay = Delay::new(&clocks); loop { led.toggle().unwrap(); delay.delay_ms(500u32); diff --git a/esp32c3-hal/examples/hello_rgb.rs b/esp32c3-hal/examples/hello_rgb.rs index 69ec94faa9f..d0ceb1e277a 100644 --- a/esp32c3-hal/examples/hello_rgb.rs +++ b/esp32c3-hal/examples/hello_rgb.rs @@ -65,7 +65,7 @@ fn main() -> ! { // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. - let mut delay = Delay::new(peripherals.SYSTIMER, &clocks); + let mut delay = Delay::new(&clocks); let mut color = Hsv { hue: 0, diff --git a/esp32c3-hal/examples/spi_loopback.rs b/esp32c3-hal/examples/spi_loopback.rs index 26df6f27e2f..53c6ece23f7 100644 --- a/esp32c3-hal/examples/spi_loopback.rs +++ b/esp32c3-hal/examples/spi_loopback.rs @@ -67,7 +67,7 @@ fn main() -> ! { &clocks, ); - let mut delay = Delay::new(peripherals.SYSTIMER, &clocks); + let mut delay = Delay::new(&clocks); loop { let mut data = [0xde, 0xca, 0xfb, 0xad]; diff --git a/esp32c3-hal/examples/systimer.rs b/esp32c3-hal/examples/systimer.rs new file mode 100644 index 00000000000..1453542987a --- /dev/null +++ b/esp32c3-hal/examples/systimer.rs @@ -0,0 +1,164 @@ +#![no_std] +#![no_main] + +use core::{cell::RefCell, fmt::Write}; + +use bare_metal::Mutex; +use esp32c3_hal::{ + pac::{self, Peripherals, UART0}, + prelude::*, + RtcCntl, + Serial, + Timer, +}; +use esp_hal_common::{ + interrupt::{self}, + systimer::{Alarm, SystemTimer, Target}, + Cpu, +}; +use panic_halt as _; +use riscv_rt::entry; + +static mut SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); +static mut ALARM0: Mutex>>> = Mutex::new(RefCell::new(None)); +static mut ALARM1: Mutex>>> = Mutex::new(RefCell::new(None)); +static mut ALARM2: Mutex>>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + + // Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT, + // the RTC WDT, and the TIMG WDTs. + let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); + let mut timer0 = Timer::new(peripherals.TIMG0); + let mut timer1 = Timer::new(peripherals.TIMG1); + let mut serial0 = Serial::new(peripherals.UART0).unwrap(); + + rtc_cntl.set_super_wdt_enable(false); + rtc_cntl.set_wdt_enable(false); + timer0.disable(); + timer1.disable(); + + writeln!(serial0, "SYSTIMER Demo start!").ok(); + + let syst = SystemTimer::new(peripherals.SYSTIMER); + + writeln!(serial0, "SYSTIMER Current value = {}", SystemTimer::now()).ok(); + + let alarm0 = syst.alarm0; + alarm0.set_target(40_000_000); + alarm0.enable_interrupt(); + + let alarm1 = syst.alarm1; + alarm1.set_target(41_111_111); + alarm1.enable_interrupt(); + + let alarm2 = syst.alarm2; + alarm2.set_target(42_222_222 * 2); + alarm2.enable_interrupt(); + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET0, + interrupt::CpuInterrupt::Interrupt1, + ); + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET1, + interrupt::CpuInterrupt::Interrupt2, + ); + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET2, + interrupt::CpuInterrupt::Interrupt3, + ); + interrupt::set_kind( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt1, + interrupt::InterruptKind::Level, + ); + interrupt::set_kind( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt2, + interrupt::InterruptKind::Level, + ); + interrupt::set_kind( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt3, + interrupt::InterruptKind::Level, + ); + interrupt::set_priority( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt1, + interrupt::Priority::Priority1, + ); + interrupt::set_priority( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt2, + interrupt::Priority::Priority1, + ); + interrupt::set_priority( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt3, + interrupt::Priority::Priority1, + ); + + riscv::interrupt::free(|_cs| unsafe { + SERIAL.get_mut().replace(Some(serial0)); + ALARM0.get_mut().replace(Some(alarm0)); + ALARM1.get_mut().replace(Some(alarm1)); + ALARM2.get_mut().replace(Some(alarm2)); + }); + + unsafe { + riscv::interrupt::enable(); + } + + loop {} +} + +#[no_mangle] +pub fn interrupt1() { + riscv::interrupt::free(|cs| unsafe { + let mut serial = SERIAL.borrow(*cs).borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt 1 = {}", SystemTimer::now()).ok(); + + let mut alarm = ALARM0.borrow(*cs).borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + + interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt1); + alarm.clear_interrupt(); + }); +} + +#[no_mangle] +pub fn interrupt2() { + riscv::interrupt::free(|cs| unsafe { + let mut serial = SERIAL.borrow(*cs).borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt 2 = {}", SystemTimer::now()).ok(); + + let mut alarm = ALARM1.borrow(*cs).borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + + interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt2); + alarm.clear_interrupt(); + }); +} + +#[no_mangle] +pub fn interrupt3() { + riscv::interrupt::free(|cs| unsafe { + let mut serial = SERIAL.borrow(*cs).borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt 3 = {}", SystemTimer::now()).ok(); + + let mut alarm = ALARM2.borrow(*cs).borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + + interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt3); + alarm.clear_interrupt(); + }); +} diff --git a/esp32c3-hal/examples/usb_serial_jtag.rs b/esp32c3-hal/examples/usb_serial_jtag.rs index abae1dc8451..3c276b874ae 100644 --- a/esp32c3-hal/examples/usb_serial_jtag.rs +++ b/esp32c3-hal/examples/usb_serial_jtag.rs @@ -21,7 +21,7 @@ fn main() -> ! { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let mut delay = Delay::new(peripherals.SYSTIMER, &clocks); + let mut delay = Delay::new(&clocks); let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); let mut timer0 = Timer::new(peripherals.TIMG0); let mut timer1 = Timer::new(peripherals.TIMG1); diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index 39ddc7cf84b..e85a4d19317 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -13,6 +13,7 @@ pub use esp_hal_common::{ ram, spi, system, + systimer, utils, Cpu, Delay, diff --git a/esp32s2-hal/examples/systimer.rs b/esp32s2-hal/examples/systimer.rs new file mode 100644 index 00000000000..39ce0fcc892 --- /dev/null +++ b/esp32s2-hal/examples/systimer.rs @@ -0,0 +1,173 @@ +#![no_std] +#![no_main] + +use core::{cell::RefCell, fmt::Write}; + +use esp32s2_hal::{ + clock::ClockControl, + pac::{self, Peripherals, UART0}, + prelude::*, + Delay, + RtcCntl, + Serial, + Timer, +}; +use esp_hal_common::{ + interrupt, + Cpu, + systimer::{SystemTimer, Alarm, Target} +}; +use panic_halt as _; +use xtensa_lx::mutex::{Mutex, CriticalSectionMutex}; +use xtensa_lx_rt::entry; + +static mut SERIAL: CriticalSectionMutex>>> = + CriticalSectionMutex::new(RefCell::new(None)); +static mut ALARM0: CriticalSectionMutex>>> = + CriticalSectionMutex::new(RefCell::new(None)); +static mut ALARM1: CriticalSectionMutex>>> = + CriticalSectionMutex::new(RefCell::new(None)); +static mut ALARM2: CriticalSectionMutex>>> = + CriticalSectionMutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut timer0 = Timer::new(peripherals.TIMG0); + let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); + let mut serial0 = Serial::new(peripherals.UART0).unwrap(); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + timer0.disable(); + rtc_cntl.set_wdt_global_enable(false); + + let syst = SystemTimer::new(peripherals.SYSTIMER); + + let now = SystemTimer::now(); + + writeln!(serial0, "Now: {}", now).ok(); + + let alarm0 = syst.alarm0; + alarm0.set_target(40_000_0000); + alarm0.enable_interrupt(); + + let alarm1 = syst.alarm1; + alarm1.set_target(41_111_1110); + alarm1.enable_interrupt(); + + let alarm2 = syst.alarm2; + alarm2.set_target(42_222_2220 * 2); + alarm2.enable_interrupt(); + + unsafe { + (&SERIAL).lock(|data| (*data).replace(Some(serial0))); + (&ALARM0).lock(|data| (*data).replace(Some(alarm0))); + (&ALARM1).lock(|data| (*data).replace(Some(alarm1))); + (&ALARM2).lock(|data| (*data).replace(Some(alarm2))); + } + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET0, + interrupt::CpuInterrupt::Interrupt0LevelPriority1, + ); + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET1, + interrupt::CpuInterrupt::Interrupt19LevelPriority2, + ); + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET2, + interrupt::CpuInterrupt::Interrupt23LevelPriority3, + ); + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + unsafe { + xtensa_lx::interrupt::enable_mask(1 << 19 | 1 << 0 | 1 << 23 ); + } + + loop { + delay.delay_ms(500u32); + } +} + +#[no_mangle] +pub fn level1_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl1 (alarm0)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt0LevelPriority1, + ); + + unsafe { + (&ALARM0).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} + +#[no_mangle] +pub fn level2_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl2 (alarm1)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt19LevelPriority2, + ); + + unsafe { + (&ALARM1).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} + +#[no_mangle] +pub fn level3_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl3 (alarm2)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt23LevelPriority3, + ); + + unsafe { + (&ALARM2).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} diff --git a/esp32s3-hal/examples/systimer.rs b/esp32s3-hal/examples/systimer.rs new file mode 100644 index 00000000000..316b3f62b2b --- /dev/null +++ b/esp32s3-hal/examples/systimer.rs @@ -0,0 +1,169 @@ +#![no_std] +#![no_main] + +use core::{cell::RefCell, fmt::Write}; + +use esp32s3_hal::{ + clock::ClockControl, + pac::{self, Peripherals, UART0}, + prelude::*, + Delay, + RtcCntl, + Serial, + Timer, +}; +use esp_hal_common::{ + interrupt, + Cpu, + systimer::{SystemTimer, Alarm, Target} +}; +use panic_halt as _; +use xtensa_lx::mutex::{Mutex, SpinLockMutex}; +use xtensa_lx_rt::entry; + +static mut SERIAL: SpinLockMutex>>> = + SpinLockMutex::new(RefCell::new(None)); +static mut ALARM0: SpinLockMutex>>> = + SpinLockMutex::new(RefCell::new(None)); +static mut ALARM1: SpinLockMutex>>> = + SpinLockMutex::new(RefCell::new(None)); +static mut ALARM2: SpinLockMutex>>> = + SpinLockMutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take().unwrap(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut timer0 = Timer::new(peripherals.TIMG0); + let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); + let serial0 = Serial::new(peripherals.UART0).unwrap(); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + timer0.disable(); + rtc_cntl.set_wdt_global_enable(false); + + let syst = SystemTimer::new(peripherals.SYSTIMER); + + let alarm0 = syst.alarm0; + alarm0.set_target(40_000_000); + alarm0.enable_interrupt(); + + let alarm1 = syst.alarm1; + alarm1.set_target(41_111_111); + alarm1.enable_interrupt(); + + let alarm2 = syst.alarm2; + alarm2.set_target(42_222_222 * 2); + alarm2.enable_interrupt(); + + unsafe { + (&SERIAL).lock(|data| (*data).replace(Some(serial0))); + (&ALARM0).lock(|data| (*data).replace(Some(alarm0))); + (&ALARM1).lock(|data| (*data).replace(Some(alarm1))); + (&ALARM2).lock(|data| (*data).replace(Some(alarm2))); + } + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET0, + interrupt::CpuInterrupt::Interrupt0LevelPriority1, + ); + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET1, + interrupt::CpuInterrupt::Interrupt19LevelPriority2, + ); + + interrupt::enable( + Cpu::ProCpu, + pac::Interrupt::SYSTIMER_TARGET2, + interrupt::CpuInterrupt::Interrupt23LevelPriority3, + ); + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + unsafe { + xtensa_lx::interrupt::enable_mask(1 << 19 | 1 << 0 | 1 << 23 ); + } + + loop { + delay.delay_ms(500u32); + } +} + +#[no_mangle] +pub fn level1_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl1 (alarm0)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt0LevelPriority1, + ); + + unsafe { + (&ALARM0).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} + +#[no_mangle] +pub fn level2_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl2 (alarm1)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt19LevelPriority2, + ); + + unsafe { + (&ALARM1).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} + +#[no_mangle] +pub fn level3_interrupt() { + unsafe { + (&SERIAL).lock(|data| { + let mut serial = data.borrow_mut(); + let serial = serial.as_mut().unwrap(); + writeln!(serial, "Interrupt lvl3 (alarm2)").ok(); + }); + } + + interrupt::clear( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt23LevelPriority3, + ); + + unsafe { + (&ALARM2).lock(|data| { + let mut alarm = data.borrow_mut(); + let alarm = alarm.as_mut().unwrap(); + alarm.clear_interrupt(); + }); + } +} diff --git a/esp32s3-hal/src/lib.rs b/esp32s3-hal/src/lib.rs index b6fe8450f40..c65ebe3e2a8 100644 --- a/esp32s3-hal/src/lib.rs +++ b/esp32s3-hal/src/lib.rs @@ -10,6 +10,7 @@ pub use esp_hal_common::{ pulse_control, ram, spi, + systimer, usb_serial_jtag, utils, Cpu,