esp_wifi/preempt_builtin/timer/
riscv.rs

1use esp_hal::interrupt::InterruptHandler;
2#[cfg(any(feature = "esp32c6", feature = "esp32h2"))]
3use peripherals::INTPRI as SystemPeripheral;
4#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
5use peripherals::SYSTEM as SystemPeripheral;
6
7use crate::{
8    hal::{
9        interrupt::{self, TrapFrame},
10        peripherals::{self, Interrupt},
11        riscv,
12        time::Rate,
13    },
14    preempt_builtin::task_switch,
15    TimeBase,
16};
17
18/// The timer responsible for time slicing.
19const TIMESLICE_FREQUENCY: Rate = Rate::from_hz(crate::CONFIG.tick_rate_hz);
20
21use super::TIMER;
22
23pub(crate) fn setup_timer(mut alarm0: TimeBase) {
24    // make sure the scheduling won't start before everything is setup
25    riscv::interrupt::disable();
26
27    let cb: extern "C" fn() = unsafe { core::mem::transmute(handler as *const ()) };
28    alarm0.set_interrupt_handler(InterruptHandler::new(cb, interrupt::Priority::Priority1));
29    unwrap!(alarm0.start(TIMESLICE_FREQUENCY.as_duration()));
30    TIMER.with(|timer| {
31        alarm0.enable_interrupt(true);
32        timer.replace(alarm0);
33    });
34}
35
36pub(crate) fn disable_timer() {
37    TIMER.with(|timer| {
38        let timer = unwrap!(timer.as_mut());
39        timer.enable_interrupt(false);
40        unwrap!(timer.cancel());
41    });
42}
43
44pub(crate) fn setup_multitasking() {
45    unwrap!(interrupt::enable(
46        Interrupt::FROM_CPU_INTR3,
47        interrupt::Priority::Priority1,
48    ));
49
50    unsafe {
51        riscv::interrupt::enable();
52    }
53}
54
55pub(crate) fn disable_multitasking() {
56    interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::FROM_CPU_INTR3);
57}
58
59extern "C" fn handler(trap_frame: &mut TrapFrame) {
60    // clear the systimer intr
61    TIMER.with(|timer| {
62        unwrap!(timer.as_mut()).clear_interrupt();
63    });
64
65    task_switch(trap_frame);
66}
67
68#[no_mangle]
69extern "C" fn FROM_CPU_INTR3(trap_frame: &mut TrapFrame) {
70    // clear FROM_CPU_INTR3
71    SystemPeripheral::regs()
72        .cpu_intr_from_cpu_3()
73        .modify(|_, w| w.cpu_intr_from_cpu_3().clear_bit());
74
75    TIMER.with(|alarm0| {
76        let alarm0 = unwrap!(alarm0.as_mut());
77        alarm0.clear_interrupt();
78    });
79
80    task_switch(trap_frame);
81}
82
83pub(crate) fn yield_task() {
84    SystemPeripheral::regs()
85        .cpu_intr_from_cpu_3()
86        .modify(|_, w| w.cpu_intr_from_cpu_3().set_bit());
87}