[esp32c3] SYSTIMER peripheral (#76)

* initial systimer impl
* Add systimer example
* Make Alarms real singletons
  * Remove runtime Option, turn into compile error
  * Make Systimer::now() not take self
* refactor shared alarm methods
* Implement esp32c3 delay with monotonic SystemTimer::now()
* Add extend systimer support to esp32s3 and add example
* systimer: esp32s2 support
This commit is contained in:
Scott Mabin 2022-06-10 15:53:45 +01:00 committed by GitHub
parent 0c61e7eeef
commit 4acdf2516c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 694 additions and 36 deletions

View File

@ -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 {}
}
}
}

View File

@ -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;

View File

@ -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<Target, 0>,
pub alarm1: Alarm<Target, 1>,
pub alarm2: Alarm<Target, 2>,
}
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<MODE, const CHANNEL: u8> {
_pd: PhantomData<MODE>,
}
impl<T, const CHANNEL: u8> Alarm<T, CHANNEL> {
// 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<const CHANNEL: u8> Alarm<Target, CHANNEL> {
pub fn set_target(&self, timestamp: u64) {
unsafe {
let systimer = &*SYSTIMER::ptr();
let (tconf, hi, lo): (
&Reg<TARGET0_CONF_SPEC>,
&Reg<TARGET0_HI_SPEC>,
&Reg<TARGET0_LO_SPEC>,
) = 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!(),
});
}
}
}

View File

@ -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();

View File

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

View File

@ -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,

View File

@ -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];

View File

@ -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<RefCell<Option<Serial<UART0>>>> = Mutex::new(RefCell::new(None));
static mut ALARM0: Mutex<RefCell<Option<Alarm<Target, 0>>>> = Mutex::new(RefCell::new(None));
static mut ALARM1: Mutex<RefCell<Option<Alarm<Target, 1>>>> = Mutex::new(RefCell::new(None));
static mut ALARM2: Mutex<RefCell<Option<Alarm<Target, 2>>>> = 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();
});
}

View File

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

View File

@ -13,6 +13,7 @@ pub use esp_hal_common::{
ram,
spi,
system,
systimer,
utils,
Cpu,
Delay,

View File

@ -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<RefCell<Option<Serial<UART0>>>> =
CriticalSectionMutex::new(RefCell::new(None));
static mut ALARM0: CriticalSectionMutex<RefCell<Option<Alarm<Target, 0>>>> =
CriticalSectionMutex::new(RefCell::new(None));
static mut ALARM1: CriticalSectionMutex<RefCell<Option<Alarm<Target, 1>>>> =
CriticalSectionMutex::new(RefCell::new(None));
static mut ALARM2: CriticalSectionMutex<RefCell<Option<Alarm<Target, 2>>>> =
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();
});
}
}

View File

@ -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<RefCell<Option<Serial<UART0>>>> =
SpinLockMutex::new(RefCell::new(None));
static mut ALARM0: SpinLockMutex<RefCell<Option<Alarm<Target, 0>>>> =
SpinLockMutex::new(RefCell::new(None));
static mut ALARM1: SpinLockMutex<RefCell<Option<Alarm<Target, 1>>>> =
SpinLockMutex::new(RefCell::new(None));
static mut ALARM2: SpinLockMutex<RefCell<Option<Alarm<Target, 2>>>> =
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();
});
}
}

View File

@ -10,6 +10,7 @@ pub use esp_hal_common::{
pulse_control,
ram,
spi,
systimer,
usb_serial_jtag,
utils,
Cpu,