工具与软件:
你(们)好、
我目前正在为我的最后一个高中项目开发裸机操作系统。 我目前在设置 DMTIMER2模块时遇到一些问题。
中断看起来像触发的、但当尝试在主循环中使用 WAIT 函数时、它由于某种原因而卡住、我不知道。
下面的代码是用铁锈写的,虽然我希望它是可读的人不熟悉铁锈。
感谢任何帮助、
此致、Felix
use crate::{
interrupts::{enable_interrupt, register_handler, Mode},
sys::{read_addr, write_addr, CM_DPLL, CM_PER},
};
const TIMER2: u32 = 0x4804_0000;
const CM_PER_L4LS_CLKCTRL: u32 = 0x60;
const CM_PER_TIMER2_CLKCTRL: u32 = 0x80;
const CLKSEL_TIMER2_CLK: u32 = 0x8;
const TIMER_CONTROL: u32 = 0x38;
const TIMER_COUNTER: u32 = 0x3C;
const TIMER_LOAD: u32 = 0x40;
const TIMER_IRQ_EOI: u32 = 0x20;
const TIMER_IRQSTATUS: u32 = 0x28;
const TIMER_IRQENABLE_SET: u32 = 0x2C;
const TIMER_IRQENABLE_CLR: u32 = 0x30;
const TIMER_RELOAD_VALUE: u32 = 0xFFFF_FFE0;
const TINT2: u32 = 68;
static mut TIMER: Timer = Timer::new();
#[allow(static_mut_refs)]
pub fn get_timer<'a>() -> &'a mut Timer {
unsafe { &mut TIMER }
}
pub fn initialize() {
let timer = get_timer();
timer.init_clocks();
timer.stop();
timer.init_timer();
timer.init_interrupt();
timer.start();
}
pub struct Timer {
counter: u32,
}
impl Timer {
const fn new() -> Self {
Timer { counter: 0 }
}
fn init_clocks(&self) {
write_addr(CM_PER + CM_PER_L4LS_CLKCTRL, 0x2);
write_addr(CM_PER + CM_PER_TIMER2_CLKCTRL, 0x2);
write_addr(CM_DPLL + CLKSEL_TIMER2_CLK, 0x2);
while read_addr(CM_PER + CM_PER_L4LS_CLKCTRL) & (0x3 << 16) != 0 {}
while read_addr(CM_PER + CM_PER_TIMER2_CLKCTRL) & (0x3 << 16) != 0 {}
}
fn init_timer(&self) {
write_addr(TIMER2 + TIMER_COUNTER, TIMER_RELOAD_VALUE);
write_addr(TIMER2 + TIMER_LOAD, TIMER_RELOAD_VALUE);
}
fn init_interrupt(&self) {
self.irq_enable();
register_handler(handle_timer_interrupt, TINT2 as usize);
enable_interrupt(TINT2, Mode::IRQ, 0);
}
fn start(&self) {
write_addr(TIMER2 + TIMER_CONTROL, 0x3);
}
fn stop(&self) {
write_addr(TIMER2 + TIMER_CONTROL, 0x0);
}
fn irq_enable(&self) {
write_addr(TIMER2 + TIMER_IRQENABLE_SET, 0x2);
}
fn irq_disable(&self) {
write_addr(TIMER2 + TIMER_IRQENABLE_CLR, 0x2);
}
fn irq_acknowledge(&self) {
write_addr(TIMER2 + TIMER_IRQ_EOI, 0x0);
write_addr(TIMER2 + TIMER_IRQSTATUS, 0x2);
}
fn increment(&mut self) {
self.counter += 1;
}
}
pub fn millis() -> u32 {
let timer = get_timer();
timer.counter
}
pub fn wait(ms: u32) {
let target = millis() + ms;
while millis() < target {}
}
fn handle_timer_interrupt() {
let timer = get_timer();
timer.irq_disable();
timer.irq_acknowledge();
timer.increment();
timer.irq_enable();
}