Add timer interrupt support and examples

This commit is contained in:
bjoernQ 2022-03-04 15:25:36 +01:00 committed by Jesse Braham
parent 6ea8916730
commit e7eea75ef8
7 changed files with 531 additions and 2 deletions

View File

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

View File

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

View File

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

View 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);
});
}
}

View 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);
});
}

View 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);
});
}
}

View 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);
});
}
}