GlobalTimer: add timer IRQ to experiment

gic: add disable individual interrupt support
mpcore: refactor icdicer registers as array
main: start timer with interrupt and add IRQ
This commit is contained in:
morgan 2023-12-14 13:02:45 +08:00
parent 535c162034
commit 1b714a8ca0
3 changed files with 49 additions and 11 deletions

View File

@ -7,6 +7,7 @@
extern crate alloc; extern crate alloc;
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use embedded_hal::blocking::delay::DelayUs;
use libasync::{ use libasync::{
delay, delay,
smoltcp::{Sockets, TcpStream}, smoltcp::{Sockets, TcpStream},
@ -25,6 +26,7 @@ use libboard_zynq::{
wire::{EthernetAddress, IpAddress, IpCidr}, wire::{EthernetAddress, IpAddress, IpCidr},
}, },
time::Milliseconds, time::Milliseconds,
timer::GlobalTimer,
}; };
#[cfg(feature = "target_zc706")] #[cfg(feature = "target_zc706")]
use libboard_zynq::print; use libboard_zynq::print;
@ -61,10 +63,19 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
let id = gic.get_interrupt_id(); let id = gic.get_interrupt_id();
match MPIDR.read().cpu_id(){ match MPIDR.read().cpu_id(){
0 => { 0 => {
if id.0 == 0 { match id.0 {
0 => {
println!("Interrupting core0..."); println!("Interrupting core0...");
gic.end_interrupt(id); gic.end_interrupt(id);
return; return;
},
27 => {
println!("GlobalTimer interrupting core0...");
GlobalTimer::clear_isr();
gic.end_interrupt(id);
return;
},
_ => {},
} }
}, },
1 => { 1 => {
@ -137,13 +148,24 @@ pub fn main_core0() {
clocks.cpu_1x() clocks.cpu_1x()
); );
let timer = libboard_zynq::timer::GlobalTimer::start(); let mut timer = GlobalTimer::start_with_interrupt(100_000);
let mut ddr = zynq::ddr::DdrRam::ddrram(); let mut ddr = zynq::ddr::DdrRam::ddrram();
#[cfg(not(feature = "target_zc706"))] #[cfg(not(feature = "target_zc706"))]
ddr.memtest(); ddr.memtest();
ram::init_alloc_ddr(&mut ddr); ram::init_alloc_ddr(&mut ddr);
info!("Enable GlobalTimer interrupt on core0");
interrupt_controller.enable(
gic::InterruptId(27),
gic::CPUCore::Core0,
gic::InterruptSensitivity::Edge,
0,
);
timer.delay_us(100_000);
interrupt_controller.disable(gic::InterruptId(27));
info!("Disable GlobalTimer interrupt");
info!("Send software interrupt to core0"); info!("Send software interrupt to core0");
interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core0.into()); interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core0.into());
info!("Core0 returned from interrupt"); info!("Core0 returned from interrupt");

View File

@ -95,6 +95,26 @@ impl InterruptController {
}.sgiintid(id.0).satt(false)); }.sgiintid(id.0).satt(false));
} }
/// disable the interrupt
pub fn disable(&mut self, id: InterruptId){
// disable
let m = (id.0 >> 5) as usize;
let n = (id.0 & 0x1F) as usize;
assert!(m < 3);
unsafe {
self.mpcore.icdicer[m].modify(|mut icdicer| *icdicer.set_bit(n, true));
}
// remove CPUs from interrupt
let m = (id.0 >> 2) as usize;
let n = (8 * (id.0 & 3)) as usize;
unsafe {
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, 0));
}
}
/// enable the interrupt *for this core*. /// enable the interrupt *for this core*.
/// Not needed for SGI. /// Not needed for SGI.
pub fn enable(&mut self, id: InterruptId, target_cpu: CPUCore, sensitivity: InterruptSensitivity, priority: u8) { pub fn enable(&mut self, id: InterruptId, target_cpu: CPUCore, sensitivity: InterruptSensitivity, priority: u8) {

View File

@ -96,12 +96,8 @@ pub struct RegisterBlock {
/// Interrupt Set-enable Registers /// Interrupt Set-enable Registers
pub icdiser: [RW<u32>; 3], pub icdiser: [RW<u32>; 3],
unused9: [u32; 29], unused9: [u32; 29],
/// Interrupt Clear-Enable Register 0 /// Interrupt Clear-Enable Register
pub icdicer0: RW<u32>, pub icdicer: [RW<u32>; 3],
/// Interrupt Clear-Enable Register 1
pub icdicer1: RW<u32>,
/// Interrupt Clear-Enable Register 2
pub icdicer2: RW<u32>,
unused10: [u32; 29], unused10: [u32; 29],
/// Interrupt Set-pending Register /// Interrupt Set-pending Register
pub icdispr0: RW<u32>, pub icdispr0: RW<u32>,