mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-29 21:30:39 +00:00
Add timer interrupt support and examples
This commit is contained in:
parent
6ea8916730
commit
e7eea75ef8
@ -5,9 +5,9 @@ use core::convert::TryInto;
|
||||
|
||||
use embedded_hal::blocking::i2c::*;
|
||||
|
||||
use crate::pac::i2c0::{RegisterBlock, COMD};
|
||||
use crate::{
|
||||
gpio::{InputPin, OutputPin},
|
||||
pac::i2c0::{RegisterBlock, COMD},
|
||||
types::{InputSignal, OutputSignal},
|
||||
};
|
||||
|
||||
|
@ -117,7 +117,7 @@ pub fn enable(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
|
||||
|
||||
// enable interrupt
|
||||
intr.cpu_int_enable
|
||||
.write(|w| w.bits(1 << cpu_interrupt_number));
|
||||
.modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,18 @@ where
|
||||
pub fn free(self) -> T {
|
||||
self.timg
|
||||
}
|
||||
|
||||
pub fn listen(&mut self) {
|
||||
self.timg.listen();
|
||||
}
|
||||
|
||||
pub fn unlisten(&mut self) {
|
||||
self.timg.unlisten();
|
||||
}
|
||||
|
||||
pub fn clear_interrupt(&mut self) {
|
||||
self.timg.clear_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/// Timer peripheral instance
|
||||
@ -124,6 +136,30 @@ pub trait Instance {
|
||||
.wdtwprotect
|
||||
.write(|w| unsafe { w.wdt_wkey().bits(0u32) });
|
||||
}
|
||||
|
||||
fn listen(&mut self) {
|
||||
// always use level interrupt
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||
self.register_block()
|
||||
.t0config
|
||||
.modify(|_, w| w.t0_level_int_en().set_bit());
|
||||
|
||||
self.register_block()
|
||||
.int_ena_timers
|
||||
.modify(|_, w| w.t0_int_ena().set_bit());
|
||||
}
|
||||
|
||||
fn unlisten(&mut self) {
|
||||
self.register_block()
|
||||
.int_ena_timers
|
||||
.modify(|_, w| w.t0_int_ena().clear_bit());
|
||||
}
|
||||
|
||||
fn clear_interrupt(&mut self) {
|
||||
self.register_block()
|
||||
.int_clr_timers
|
||||
.write(|w| w.t0_int_clr().set_bit());
|
||||
}
|
||||
}
|
||||
|
||||
impl Instance for TIMG0 {
|
||||
|
123
esp32-hal/examples/timer_interrupt.rs
Normal file
123
esp32-hal/examples/timer_interrupt.rs
Normal file
@ -0,0 +1,123 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use esp32_hal::{
|
||||
pac::{self, Peripherals, TIMG0, TIMG1, UART0},
|
||||
prelude::*,
|
||||
RtcCntl,
|
||||
Serial,
|
||||
Timer,
|
||||
};
|
||||
use esp_hal_common::{interrupt, Cpu};
|
||||
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 TIMER0: SpinLockMutex<RefCell<Option<Timer<TIMG0>>>> =
|
||||
SpinLockMutex::new(RefCell::new(None));
|
||||
static mut TIMER1: SpinLockMutex<RefCell<Option<Timer<TIMG1>>>> =
|
||||
SpinLockMutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
// Disable the TIMG watchdog timer.
|
||||
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||
let mut timer1 = Timer::new(peripherals.TIMG1);
|
||||
let serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||
|
||||
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||
timer0.disable();
|
||||
timer1.disable();
|
||||
rtc_cntl.set_wdt_global_enable(false);
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG0_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
timer0.start(50_000_000u64);
|
||||
timer0.listen();
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG1_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
timer1.start(100_000_000u64);
|
||||
timer1.listen();
|
||||
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| (*data).replace(Some(serial0)));
|
||||
(&TIMER0).lock(|data| (*data).replace(Some(timer0)));
|
||||
(&TIMER1).lock(|data| (*data).replace(Some(timer1)));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
xtensa_lx::interrupt::disable();
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level2.mask(),
|
||||
);
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level4.mask(),
|
||||
);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[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 Level 2").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER0).lock(|data| {
|
||||
let mut timer0 = data.borrow_mut();
|
||||
let timer0 = timer0.as_mut().unwrap();
|
||||
timer0.clear_interrupt();
|
||||
timer0.start(50_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn level4_interrupt() {
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| {
|
||||
let mut serial = data.borrow_mut();
|
||||
let serial = serial.as_mut().unwrap();
|
||||
writeln!(serial, "Interrupt Level 4").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER1).lock(|data| {
|
||||
let mut timer1 = data.borrow_mut();
|
||||
let timer1 = timer1.as_mut().unwrap();
|
||||
timer1.clear_interrupt();
|
||||
timer1.start(100_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
124
esp32c3-hal/examples/timer_interrupt.rs
Normal file
124
esp32c3-hal/examples/timer_interrupt.rs
Normal file
@ -0,0 +1,124 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use bare_metal::Mutex;
|
||||
use esp32c3_hal::{
|
||||
pac::{self, Peripherals, TIMG0, TIMG1, UART0},
|
||||
prelude::*,
|
||||
RtcCntl,
|
||||
Serial,
|
||||
Timer,
|
||||
};
|
||||
use esp_hal_common::{
|
||||
interrupt::{self},
|
||||
Cpu,
|
||||
};
|
||||
use panic_halt as _;
|
||||
use riscv_rt::entry;
|
||||
|
||||
static mut SERIAL: Mutex<RefCell<Option<Serial<UART0>>>> = Mutex::new(RefCell::new(None));
|
||||
static mut TIMER0: Mutex<RefCell<Option<Timer<TIMG0>>>> = Mutex::new(RefCell::new(None));
|
||||
static mut TIMER1: Mutex<RefCell<Option<Timer<TIMG1>>>> = 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 serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||
|
||||
rtc_cntl.set_super_wdt_enable(false);
|
||||
rtc_cntl.set_wdt_enable(false);
|
||||
timer0.disable();
|
||||
timer1.disable();
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG0_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt1,
|
||||
);
|
||||
interrupt::set_kind(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt1,
|
||||
interrupt::InterruptKind::Level,
|
||||
);
|
||||
interrupt::set_priority(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt1,
|
||||
interrupt::Priority::Priority1,
|
||||
);
|
||||
|
||||
timer0.start(10_000_000u64);
|
||||
timer0.listen();
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG1_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt11,
|
||||
);
|
||||
interrupt::set_kind(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt11,
|
||||
interrupt::InterruptKind::Level,
|
||||
);
|
||||
interrupt::set_priority(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt11,
|
||||
interrupt::Priority::Priority1,
|
||||
);
|
||||
|
||||
timer1.start(20_000_000u64);
|
||||
timer1.listen();
|
||||
|
||||
riscv::interrupt::free(|_cs| unsafe {
|
||||
SERIAL.get_mut().replace(Some(serial0));
|
||||
TIMER0.get_mut().replace(Some(timer0));
|
||||
TIMER1.get_mut().replace(Some(timer1));
|
||||
});
|
||||
|
||||
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").ok();
|
||||
|
||||
let mut timer0 = TIMER0.borrow(*cs).borrow_mut();
|
||||
let timer0 = timer0.as_mut().unwrap();
|
||||
|
||||
interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt1);
|
||||
timer0.clear_interrupt();
|
||||
|
||||
timer0.start(10_000_000u64);
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn interrupt11() {
|
||||
riscv::interrupt::free(|cs| unsafe {
|
||||
let mut serial = SERIAL.borrow(*cs).borrow_mut();
|
||||
let serial = serial.as_mut().unwrap();
|
||||
writeln!(serial, "Interrupt 11").ok();
|
||||
|
||||
let mut timer1 = TIMER1.borrow(*cs).borrow_mut();
|
||||
let timer1 = timer1.as_mut().unwrap();
|
||||
|
||||
interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt11);
|
||||
timer1.clear_interrupt();
|
||||
|
||||
timer1.start(20_000_000u64);
|
||||
});
|
||||
}
|
123
esp32s2-hal/examples/timer_interrupt.rs
Normal file
123
esp32s2-hal/examples/timer_interrupt.rs
Normal file
@ -0,0 +1,123 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use esp32s2_hal::{
|
||||
pac::{self, Peripherals, TIMG0, TIMG1, UART0},
|
||||
prelude::*,
|
||||
RtcCntl,
|
||||
Serial,
|
||||
Timer,
|
||||
};
|
||||
use esp_hal_common::{interrupt, Cpu};
|
||||
use panic_halt as _;
|
||||
use xtensa_lx::mutex::{CriticalSectionMutex, Mutex};
|
||||
use xtensa_lx_rt::entry;
|
||||
|
||||
static mut SERIAL: CriticalSectionMutex<RefCell<Option<Serial<UART0>>>> =
|
||||
CriticalSectionMutex::new(RefCell::new(None));
|
||||
static mut TIMER0: CriticalSectionMutex<RefCell<Option<Timer<TIMG0>>>> =
|
||||
CriticalSectionMutex::new(RefCell::new(None));
|
||||
static mut TIMER1: CriticalSectionMutex<RefCell<Option<Timer<TIMG1>>>> =
|
||||
CriticalSectionMutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
// Disable the TIMG watchdog timer.
|
||||
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||
let mut timer1 = Timer::new(peripherals.TIMG1);
|
||||
let serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||
|
||||
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||
timer0.disable();
|
||||
timer1.disable();
|
||||
rtc_cntl.set_wdt_global_enable(false);
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG0_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
timer0.start(50_000_000u64);
|
||||
timer0.listen();
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG1_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
timer1.start(100_000_000u64);
|
||||
timer1.listen();
|
||||
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| (*data).replace(Some(serial0)));
|
||||
(&TIMER0).lock(|data| (*data).replace(Some(timer0)));
|
||||
(&TIMER1).lock(|data| (*data).replace(Some(timer1)));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
xtensa_lx::interrupt::disable();
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level2.mask(),
|
||||
);
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level4.mask(),
|
||||
);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[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 Level 2").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER0).lock(|data| {
|
||||
let mut timer0 = data.borrow_mut();
|
||||
let timer0 = timer0.as_mut().unwrap();
|
||||
timer0.clear_interrupt();
|
||||
timer0.start(50_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn level4_interrupt() {
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| {
|
||||
let mut serial = data.borrow_mut();
|
||||
let serial = serial.as_mut().unwrap();
|
||||
writeln!(serial, "Interrupt Level 4").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER1).lock(|data| {
|
||||
let mut timer1 = data.borrow_mut();
|
||||
let timer1 = timer1.as_mut().unwrap();
|
||||
timer1.clear_interrupt();
|
||||
timer1.start(100_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
123
esp32s3-hal/examples/timer_interrupt.rs
Normal file
123
esp32s3-hal/examples/timer_interrupt.rs
Normal file
@ -0,0 +1,123 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use esp32s3_hal::{
|
||||
pac::{self, Peripherals, TIMG0, TIMG1, UART0},
|
||||
prelude::*,
|
||||
RtcCntl,
|
||||
Serial,
|
||||
Timer,
|
||||
};
|
||||
use esp_hal_common::{interrupt, Cpu};
|
||||
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 TIMER0: SpinLockMutex<RefCell<Option<Timer<TIMG0>>>> =
|
||||
SpinLockMutex::new(RefCell::new(None));
|
||||
static mut TIMER1: SpinLockMutex<RefCell<Option<Timer<TIMG1>>>> =
|
||||
SpinLockMutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
// Disable the TIMG watchdog timer.
|
||||
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||
let mut timer1 = Timer::new(peripherals.TIMG1);
|
||||
let serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||
|
||||
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||
timer0.disable();
|
||||
timer1.disable();
|
||||
rtc_cntl.set_wdt_global_enable(false);
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG0_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
timer0.start(50_000_000u64);
|
||||
timer0.listen();
|
||||
|
||||
interrupt::enable(
|
||||
Cpu::ProCpu,
|
||||
pac::Interrupt::TG1_T0_LEVEL,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
timer1.start(100_000_000u64);
|
||||
timer1.listen();
|
||||
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| (*data).replace(Some(serial0)));
|
||||
(&TIMER0).lock(|data| (*data).replace(Some(timer0)));
|
||||
(&TIMER1).lock(|data| (*data).replace(Some(timer1)));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
xtensa_lx::interrupt::disable();
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level2.mask(),
|
||||
);
|
||||
xtensa_lx::interrupt::enable_mask(
|
||||
xtensa_lx_rt::interrupt::CpuInterruptLevel::Level4.mask(),
|
||||
);
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[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 Level 2").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt20LevelPriority2,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER0).lock(|data| {
|
||||
let mut timer0 = data.borrow_mut();
|
||||
let timer0 = timer0.as_mut().unwrap();
|
||||
timer0.clear_interrupt();
|
||||
timer0.start(50_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn level4_interrupt() {
|
||||
unsafe {
|
||||
(&SERIAL).lock(|data| {
|
||||
let mut serial = data.borrow_mut();
|
||||
let serial = serial.as_mut().unwrap();
|
||||
writeln!(serial, "Interrupt Level 4").ok();
|
||||
});
|
||||
}
|
||||
|
||||
interrupt::clear(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt24LevelPriority4,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
(&TIMER1).lock(|data| {
|
||||
let mut timer1 = data.borrow_mut();
|
||||
let timer1 = timer1.as_mut().unwrap();
|
||||
timer1.clear_interrupt();
|
||||
timer1.start(100_000_000u64);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user