Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Found PERIPHBASE 0xf0000000
Creating GIC driver @ 0xf0000000 / 0xf0100000
Calling git.setup(0)
cntfrq = 62.500 MHz
Using physical timer ************************
Print five, every 100ms...
Expand Down
17 changes: 10 additions & 7 deletions examples/mps3-an536/src/bin/generic_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,29 @@ use cortex_r_rt::entry;
// pull in our library
use mps3_an536 as _;

use cortex_ar::generic_timer::GenericTimer;

use semihosting::println;

/// The entry-point to the Rust application.
///
/// It is called by the start-up code in `cortex-r-rt`.
#[entry]
fn main() -> ! {
use cortex_ar::generic_timer::{El1PhysicalTimer, El1VirtualTimer, GenericTimer};
let mut board = mps3_an536::Board::new().unwrap();

let cntfrq = cortex_ar::register::Cntfrq::read().0;
println!("cntfrq = {:.03} MHz", cntfrq as f32 / 1_000_000.0);

let delay_ticks = cntfrq / 2;

let mut pgt = unsafe { El1PhysicalTimer::new() };
let mut vgt = unsafe { El1VirtualTimer::new() };

let pgt_ref: &mut dyn GenericTimer = &mut pgt;
let vgt_ref: &mut dyn GenericTimer = &mut vgt;
let physical_timer_ref: &mut dyn GenericTimer = &mut board.physical_timer;
let virtual_timer_ref: &mut dyn GenericTimer = &mut board.virtual_timer;

for (timer, name) in [(pgt_ref, "physical"), (vgt_ref, "virtual")] {
for (timer, name) in [
(physical_timer_ref, "physical"),
(virtual_timer_ref, "virtual"),
] {
println!("Using {} timer ************************", name);

println!("Print five, every 100ms...");
Expand Down
74 changes: 28 additions & 46 deletions examples/mps3-an536/src/bin/generic_timer_irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,47 @@
#![no_main]

use arm_gic::{
gicv3::{GicCpuInterface, GicV3, Group, InterruptGroup},
IntId, UniqueMmioPointer,
gicv3::{GicCpuInterface, Group, InterruptGroup},
IntId,
};
use core::ptr::NonNull;
use cortex_ar::generic_timer::{El1VirtualTimer, GenericTimer};
use cortex_r_rt::{entry, irq};
use mps3_an536 as _;
use mps3_an536::VIRTUAL_TIMER_PPI;
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;

/// The PPI for the virutal timer, according to the Cortex-R52 Technical Reference Manual,
/// Table 10-3: PPI assignments.
///
/// This corresponds to Interrupt ID 27.
const VIRTUAL_TIMER_PPI: IntId = IntId::ppi(11);

/// 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);
let mut board = mps3_an536::Board::new().unwrap();

// Initialise the GIC.
println!(
"Creating GIC driver @ {:010p} / {:010p}",
gicd_base, gicr_base
);
let gicd = unsafe { UniqueMmioPointer::new(NonNull::new(gicd_base.cast()).unwrap()) };
let gicr = NonNull::new(gicr_base.cast()).unwrap();
let mut gic = unsafe { GicV3::new(gicd, gicr, 1, false) };

println!("Calling git.setup(0)");
gic.setup(0);
// Only interrupts with a higher priority (numerically lower) will be signalled.
GicCpuInterface::set_priority_mask(0x80);

println!("Configure Timer Interrupt...");
gic.set_interrupt_priority(VIRTUAL_TIMER_PPI, Some(0), 0x31)
board
.gic
.set_interrupt_priority(VIRTUAL_TIMER_PPI, Some(0), 0x31)
.unwrap();
gic.set_group(VIRTUAL_TIMER_PPI, Some(0), Group::Group1NS)
board
.gic
.set_group(VIRTUAL_TIMER_PPI, Some(0), Group::Group1NS)
.unwrap();
gic.enable_interrupt(VIRTUAL_TIMER_PPI, Some(0), true)
board
.gic
.enable_interrupt(VIRTUAL_TIMER_PPI, Some(0), true)
.unwrap();

// Create virtual timer, run as up-counter.
let mut vgt = unsafe { El1VirtualTimer::new() };
vgt.enable(true);
vgt.interrupt_mask(false);
vgt.counter_compare_set(vgt.counter().wrapping_add(vgt.frequency_hz() as u64));

drop(vgt); // Drop to free the timer handle.
// Setup virtual timer
board.virtual_timer.enable(true);
board.virtual_timer.interrupt_mask(false);
board.virtual_timer.counter_compare_set(
board
.virtual_timer
.counter()
.wrapping_add(board.virtual_timer.frequency_hz() as u64 / 5),
);

println!("Enabling interrupts...");
dump_cpsr();
Expand Down Expand Up @@ -107,11 +88,12 @@ fn irq_handler() {
/// Run when the timer IRQ fires
fn handle_timer_irq() {
// SAFETY: We drop en other time handle in main, this is the only active handle.
let mut vgt = unsafe { El1VirtualTimer::new() };
let mut virtual_timer = unsafe { El1VirtualTimer::new() };
// trigger a timer in 0.2 seconds
vgt.counter_compare_set(
vgt.counter_compare()
.wrapping_add(vgt.frequency_hz() as u64 / 5),
virtual_timer.counter_compare_set(
virtual_timer
.counter_compare()
.wrapping_add(virtual_timer.frequency_hz() as u64 / 5),
);

println!(" - Timer fired, resetting");
Expand Down
61 changes: 27 additions & 34 deletions examples/mps3-an536/src/bin/gic-map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@ use cortex_r_rt::{entry, irq};
use mps3_an536::InterruptHandler;

use arm_gic::{
gicv3::{GicCpuInterface, GicV3, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
IntId, UniqueMmioPointer,
gicv3::{GicCpuInterface, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
IntId,
};
use core::{cell::RefCell, ptr::NonNull};
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);

Expand All @@ -36,42 +30,41 @@ static INTERRUPT_HANDLERS: critical_section::Mutex<RefCell<LinearMap<IntId, Inte
/// 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 gicd = unsafe { UniqueMmioPointer::new(NonNull::new(gicd_base.cast()).unwrap()) };
let gicr = NonNull::new(gicr_base.cast()).unwrap();
let mut gic = unsafe { GicV3::new(gicd, gicr, 1, false) };

println!("Calling git.setup(0)");
gic.setup(0);
let mut board = mps3_an536::Board::new().unwrap();

// Only interrupts with a higher priority (numerically lower) will be signalled.
GicCpuInterface::set_priority_mask(0x80);

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

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

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

critical_section::with(|cs| {
let mut handlers = INTERRUPT_HANDLERS.borrow_ref_mut(cs);
Expand Down
58 changes: 25 additions & 33 deletions examples/mps3-an536/src/bin/gic-priority-ceiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,18 @@
#![no_std]
#![no_main]

use core::ptr::NonNull;

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

// pull in our library
use mps3_an536 as _;

use arm_gic::{
gicv3::{GicCpuInterface, GicV3, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
IntId, UniqueMmioPointer,
gicv3::{GicCpuInterface, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
IntId,
};
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);

Expand All @@ -36,41 +28,41 @@ const HIGH_PRIORITY: u8 = 0x10;
/// 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 gicd = unsafe { UniqueMmioPointer::new(NonNull::new(gicd_base.cast()).unwrap()) };
let gicr = NonNull::new(gicr_base.cast()).unwrap();
let mut gic = unsafe { GicV3::new(gicd, gicr, 1, false) };

println!("Calling git.setup(0)");
gic.setup(0);
let mut board = mps3_an536::Board::new().unwrap();

// Only interrupts with a higher priority (numerically lower) will be signalled.
GicCpuInterface::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), LOW_PRIORITY)
board
.gic
.set_interrupt_priority(SGI_INTID_LO, Some(0), LOW_PRIORITY)
.unwrap();
gic.set_group(SGI_INTID_LO, Some(0), Group::Group1NS)
board
.gic
.set_group(SGI_INTID_LO, Some(0), Group::Group1NS)
.unwrap();

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

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

println!("Enabling interrupts...");
dump_cpsr();
Expand Down
Loading