Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions examples/mps3-an536/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ version = "0.0.0"
cortex-ar = { path = "../../cortex-ar", features = ["critical-section-multi-core"] }
cortex-r-rt = { path = "../../cortex-r-rt" }
semihosting = { version = "0.1.18", features = ["stdio"] }
arm-gic = { git = "https://github.com/google/arm-gic.git", rev = "46a8fc1720f5c28fccf4dfb5953b88dab7012e9c", optional = true }
arm-gic = { version = "0.6.1", optional = true }
critical-section = "1.2.0"
heapless = "0.9.1"

[build-dependencies]
arm-targets = {version = "0.2.0", path = "../../arm-targets"}
Expand All @@ -30,5 +31,13 @@ eabi-fpu = ["cortex-r-rt/eabi-fpu"]
gic = ["arm-gic"]

[[bin]]
name = "gic"
name = "gic-map"
required-features = ["gic"]

[[bin]]
name = "gic-static-section-irq"
required-features = ["gic"]

[[bin]]
name = "gic-unified-irq"
required-features = ["gic"]
19 changes: 19 additions & 0 deletions examples/mps3-an536/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,22 @@ MEMORY {
REGION_ALIAS("VECTORS", QSPI);
REGION_ALIAS("CODE", QSPI);
REGION_ALIAS("DATA", DDR);

SECTIONS {
/* ### Interrupt Handler Entries
*
* The IRQ handler walks this section to find registered
* interrupt handlers
*/
.irq_entries : ALIGN(4)
{
/* We put this in the header */
__irq_entries_start = .;
/* Here are the entries */
KEEP(*(.irq_entries));
/* Keep this block a nice round size */
. = ALIGN(4);
/* We put this in the header */
__irq_entries_end = .;
} > CODE
} INSERT AFTER .text;

This file was deleted.

20 changes: 20 additions & 0 deletions examples/mps3-an536/reference/gic-map-armv8r-none-eabihf.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Found PERIPHBASE 0xf0000000
Creating GIC driver @ 0xf0000000 / 0xf0100000
Calling git.setup(0)
Configure low-prio SGI...
Configure high-prio SGI...
gic.enable_interrupt()
Enabling interrupts...
CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=1 F=1 T=0 MODE=Ok(Sys) }
CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=0 F=1 T=0 MODE=Ok(Sys) }
Send lo-prio SGI
> IRQ
- handle_interrupt_with_id(SGI 3)
- got SGI 3, sending hi-prio SGI 4
> IRQ
- handle_interrupt_with_id(SGI 4)
- got hi-prio SGI 4!
< IRQ
- finished sending hi-prio!
< IRQ
IRQ test completed OK
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Found PERIPHBASE 0xf0000000
Creating GIC driver @ 0xf0000000 / 0xf0100000
Calling git.setup(0)
Configure low-prio SGI...
Configure high-prio SGI...
gic.enable_interrupt()
Enabling interrupts...
CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=1 F=1 T=0 MODE=Ok(Sys) }
CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=0 F=1 T=0 MODE=Ok(Sys) }
Send lo-prio SGI
> IRQ
- handle_interrupt_with_id(SGI 3)
- got SGI 3, sending hi-prio SGI 4
> IRQ
- handle_interrupt_with_id(SGI 4)
- got hi-prio SGI 4!
< IRQ
- finished sending hi-prio!
< IRQ
IRQ test completed OK
166 changes: 166 additions & 0 deletions examples/mps3-an536/src/bin/gic-map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//! # GIC example for Arm Cortex-R52 on an MPS2-AN336
//!
//! Uses a run-time map of interrupt handlers.

#![no_std]
#![no_main]

// pull in our start-up code
use cortex_r_rt::{entry, irq};

// pull in our library
use mps3_an536::InterruptHandler;

use arm_gic::{
gicv3::{GicV3, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
IntId,
};
use core::cell::RefCell;
use heapless::linear_map::LinearMap;
use semihosting::println;

/// Offset from PERIPHBASE for GIC Distributor
const GICD_BASE_OFFSET: usize = 0x0000_0000usize;

/// Offset from PERIPHBASE for the first GIC Redistributor
const GICR_BASE_OFFSET: usize = 0x0010_0000usize;

const SGI_INTID_LO: IntId = IntId::sgi(3);
const SGI_INTID_HI: IntId = IntId::sgi(4);

static INTERRUPT_HANDLERS: critical_section::Mutex<RefCell<LinearMap<IntId, InterruptHandler, 8>>> =
critical_section::Mutex::new(RefCell::new(LinearMap::new()));

/// The entry-point to the Rust application.
///
/// It is called by the start-up code in `cortex-r-rt`.
#[entry]
fn main() -> ! {
// Get the GIC address by reading CBAR
let periphbase = cortex_ar::register::ImpCbar::read().periphbase();
println!("Found PERIPHBASE {:010p}", periphbase);
let gicd_base = periphbase.wrapping_byte_add(GICD_BASE_OFFSET);
let gicr_base = periphbase.wrapping_byte_add(GICR_BASE_OFFSET);

// Initialise the GIC.
println!(
"Creating GIC driver @ {:010p} / {:010p}",
gicd_base, gicr_base
);
let mut gic: GicV3 = unsafe { GicV3::new(gicd_base.cast(), gicr_base.cast(), 1, false) };
println!("Calling git.setup(0)");
gic.setup(0);
GicV3::set_priority_mask(0x80);

// Configure a Software Generated Interrupt for Core 0
println!("Configure low-prio SGI...");
gic.set_interrupt_priority(SGI_INTID_LO, Some(0), 0x31);
gic.set_group(SGI_INTID_LO, Some(0), Group::Group1NS);

println!("Configure high-prio SGI...");
gic.set_interrupt_priority(SGI_INTID_HI, Some(0), 0x10);
gic.set_group(SGI_INTID_HI, Some(0), Group::Group1NS);

println!("gic.enable_interrupt()");
gic.enable_interrupt(SGI_INTID_LO, Some(0), true);
gic.enable_interrupt(SGI_INTID_HI, Some(0), true);

critical_section::with(|cs| {
let mut handlers = INTERRUPT_HANDLERS.borrow_ref_mut(cs);
handlers
.insert(
SGI_INTID_LO,
InterruptHandler::new(SGI_INTID_LO, handle_sgi_lo),
)
.unwrap();
handlers
.insert(
SGI_INTID_HI,
InterruptHandler::new(SGI_INTID_HI, handle_sgi_hi),
)
.unwrap();
});

println!("Enabling interrupts...");
dump_cpsr();
unsafe {
cortex_ar::interrupt::enable();
}
dump_cpsr();

// Send it
println!("Send lo-prio SGI");
GicV3::send_sgi(
SGI_INTID_LO,
SgiTarget::List {
affinity3: 0,
affinity2: 0,
affinity1: 0,
target_list: 0b1,
},
SgiTargetGroup::CurrentGroup1,
);

for _ in 0..1_000_000 {
cortex_ar::asm::nop();
}

println!("IRQ test completed OK");

semihosting::process::exit(0);
}

fn dump_cpsr() {
let cpsr = cortex_ar::register::Cpsr::read();
println!("CPSR: {:?}", cpsr);
}

/// Handles the low-prio SGI
fn handle_sgi_lo(int_id: IntId) {
println!("- got {:?}, sending hi-prio {:?}", int_id, SGI_INTID_HI);
GicV3::send_sgi(
SGI_INTID_HI,
SgiTarget::List {
affinity3: 0,
affinity2: 0,
affinity1: 0,
target_list: 0b1,
},
SgiTargetGroup::CurrentGroup1,
);
println!("- finished sending hi-prio!");
}

/// Handles the high-prio SGI
fn handle_sgi_hi(int_id: IntId) {
println!("- got hi-prio {:?}!", int_id);
}

/// Called when the Arm CPU gets an IRQ
///
/// Talks to the GICv3 to find out which interrupts are pending and calls
/// [`handle_interrupt_with_id`] for each of them, with interrupts re-enabled.
#[cfg(feature = "gic")]
#[irq]
fn irq_handler() {
println!("> IRQ");
while let Some(next_int_id) = GicV3::get_and_acknowledge_interrupt(InterruptGroup::Group1) {
// handle the interrupt
println!("- handle_interrupt_with_id({:?})", next_int_id);
let handler = critical_section::with(|cs| {
let handlers_map = INTERRUPT_HANDLERS.borrow_ref(cs);
handlers_map.get(&next_int_id).cloned()
});
if let Some(irq_entry) = handler {
// let's go re-entrant
unsafe {
cortex_ar::interrupt::enable();
}
irq_entry.execute();
// turn interrupts off again
cortex_ar::interrupt::disable();
}
GicV3::end_interrupt(next_int_id, InterruptGroup::Group1);
}
println!("< IRQ");
}
Loading