diff --git a/experiments/src/main.rs b/experiments/src/main.rs index 41278aa..c63e066 100644 --- a/experiments/src/main.rs +++ b/experiments/src/main.rs @@ -7,6 +7,7 @@ extern crate alloc; use alloc::collections::BTreeMap; +use embedded_hal::blocking::delay::DelayUs; use libasync::{ delay, smoltcp::{Sockets, TcpStream}, @@ -25,6 +26,7 @@ use libboard_zynq::{ wire::{EthernetAddress, IpAddress, IpCidr}, }, time::Milliseconds, + timer::GlobalTimer, }; #[cfg(feature = "target_zc706")] use libboard_zynq::print; @@ -61,10 +63,19 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, { let id = gic.get_interrupt_id(); match MPIDR.read().cpu_id(){ 0 => { - if id.0 == 0 { - println!("Interrupting core0..."); - gic.end_interrupt(id); - return; + match id.0 { + 0 => { + println!("Interrupting core0..."); + gic.end_interrupt(id); + return; + }, + 27 => { + println!("GlobalTimer interrupting core0..."); + GlobalTimer::clear_isr(); + gic.end_interrupt(id); + return; + }, + _ => {}, } }, 1 => { @@ -137,13 +148,24 @@ pub fn main_core0() { 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(); #[cfg(not(feature = "target_zc706"))] ddr.memtest(); 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"); interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core0.into()); info!("Core0 returned from interrupt"); diff --git a/libboard_zynq/src/gic.rs b/libboard_zynq/src/gic.rs index fc962c6..876bee5 100644 --- a/libboard_zynq/src/gic.rs +++ b/libboard_zynq/src/gic.rs @@ -95,6 +95,26 @@ impl InterruptController { }.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*. /// Not needed for SGI. pub fn enable(&mut self, id: InterruptId, target_cpu: CPUCore, sensitivity: InterruptSensitivity, priority: u8) { diff --git a/libboard_zynq/src/mpcore.rs b/libboard_zynq/src/mpcore.rs index c1baf8b..f82ab42 100644 --- a/libboard_zynq/src/mpcore.rs +++ b/libboard_zynq/src/mpcore.rs @@ -96,12 +96,8 @@ pub struct RegisterBlock { /// Interrupt Set-enable Registers pub icdiser: [RW; 3], unused9: [u32; 29], - /// Interrupt Clear-Enable Register 0 - pub icdicer0: RW, - /// Interrupt Clear-Enable Register 1 - pub icdicer1: RW, - /// Interrupt Clear-Enable Register 2 - pub icdicer2: RW, + /// Interrupt Clear-Enable Register + pub icdicer: [RW; 3], unused10: [u32; 29], /// Interrupt Set-pending Register pub icdispr0: RW,