Skip to content

Commit d7ae927

Browse files
Merge pull request #72 from korken89/priority-celining-example
Add priority ceiling example
2 parents 1f20e79 + 2c26558 commit d7ae927

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

examples/mps3-an536/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@ required-features = ["gic"]
4545
[[bin]]
4646
name = "generic_timer_irq"
4747
required-features = ["gic"]
48+
49+
[[bin]]
50+
name = "gic-priority-ceiling"
51+
required-features = ["gic"]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Found PERIPHBASE 0xf0000000
2+
Creating GIC driver @ 0xf0000000 / 0xf0100000
3+
Calling git.setup(0)
4+
Configure low-prio SGI...
5+
Configure high-prio SGI...
6+
gic.enable_interrupt()
7+
Enabling interrupts...
8+
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) }
9+
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) }
10+
Send lo-prio SGI
11+
> IRQ
12+
- IRQ Handling SGI 3
13+
- Low prio!
14+
- Pre lock exit
15+
- HIGH PRIO SHOULD RUN AFTER THIS
16+
> IRQ
17+
- IRQ Handling SGI 4
18+
- High prio!
19+
< IRQ
20+
- HIGH PRIO SHOULD RUN BEFORE THIS
21+
- Post lock exit
22+
< IRQ
23+
IRQ test completed OK
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
//! GIC example to implement Priority Ceilings for Arm Cortex-R52 on an MPS2-AN336
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
use core::ptr::NonNull;
7+
8+
// pull in our start-up code
9+
use cortex_r_rt::{entry, irq};
10+
11+
// pull in our library
12+
use mps3_an536 as _;
13+
14+
use arm_gic::{
15+
gicv3::{GicCpuInterface, GicV3, Group, InterruptGroup, SgiTarget, SgiTargetGroup},
16+
IntId, UniqueMmioPointer,
17+
};
18+
use semihosting::println;
19+
20+
/// Offset from PERIPHBASE for GIC Distributor
21+
const GICD_BASE_OFFSET: usize = 0x0000_0000usize;
22+
23+
/// Offset from PERIPHBASE for the first GIC Redistributor
24+
const GICR_BASE_OFFSET: usize = 0x0010_0000usize;
25+
26+
const SGI_INTID_LO: IntId = IntId::sgi(3);
27+
const SGI_INTID_HI: IntId = IntId::sgi(4);
28+
29+
// Priority for `SGI_INTID_LO`
30+
const LOW_PRIORITY: u8 = 0x31;
31+
// Priority for `SGI_INTID_HI`
32+
const HIGH_PRIORITY: u8 = 0x10;
33+
34+
/// The entry-point to the Rust application.
35+
///
36+
/// It is called by the start-up code in `cortex-r-rt`.
37+
#[entry]
38+
fn main() -> ! {
39+
// Get the GIC address by reading CBAR
40+
let periphbase = cortex_ar::register::ImpCbar::read().periphbase();
41+
println!("Found PERIPHBASE {:010p}", periphbase);
42+
let gicd_base = periphbase.wrapping_byte_add(GICD_BASE_OFFSET);
43+
let gicr_base = periphbase.wrapping_byte_add(GICR_BASE_OFFSET);
44+
45+
// Initialise the GIC.
46+
println!(
47+
"Creating GIC driver @ {:010p} / {:010p}",
48+
gicd_base, gicr_base
49+
);
50+
let gicd = unsafe { UniqueMmioPointer::new(NonNull::new(gicd_base.cast()).unwrap()) };
51+
let gicr = NonNull::new(gicr_base.cast()).unwrap();
52+
let mut gic = unsafe { GicV3::new(gicd, gicr, 1, false) };
53+
54+
println!("Calling git.setup(0)");
55+
gic.setup(0);
56+
GicCpuInterface::set_priority_mask(0x80);
57+
58+
// Configure a Software Generated Interrupt for Core 0
59+
println!("Configure low-prio SGI...");
60+
gic.set_interrupt_priority(SGI_INTID_LO, Some(0), LOW_PRIORITY)
61+
.unwrap();
62+
gic.set_group(SGI_INTID_LO, Some(0), Group::Group1NS)
63+
.unwrap();
64+
65+
println!("Configure high-prio SGI...");
66+
gic.set_interrupt_priority(SGI_INTID_HI, Some(0), HIGH_PRIORITY)
67+
.unwrap();
68+
gic.set_group(SGI_INTID_HI, Some(0), Group::Group1NS)
69+
.unwrap();
70+
71+
println!("gic.enable_interrupt()");
72+
gic.enable_interrupt(SGI_INTID_LO, Some(0), true).unwrap();
73+
gic.enable_interrupt(SGI_INTID_HI, Some(0), true).unwrap();
74+
75+
println!("Enabling interrupts...");
76+
dump_cpsr();
77+
unsafe {
78+
cortex_ar::interrupt::enable();
79+
}
80+
dump_cpsr();
81+
82+
// Send it
83+
println!("Send lo-prio SGI");
84+
GicCpuInterface::send_sgi(
85+
SGI_INTID_LO,
86+
SgiTarget::List {
87+
affinity3: 0,
88+
affinity2: 0,
89+
affinity1: 0,
90+
target_list: 0b1,
91+
},
92+
SgiTargetGroup::CurrentGroup1,
93+
)
94+
.unwrap();
95+
96+
for _ in 0..1_000_000 {
97+
cortex_ar::asm::nop();
98+
}
99+
100+
println!("IRQ test completed OK");
101+
102+
semihosting::process::exit(0);
103+
}
104+
105+
fn dump_cpsr() {
106+
let cpsr = cortex_ar::register::Cpsr::read();
107+
println!("CPSR: {:?}", cpsr);
108+
}
109+
110+
#[irq]
111+
fn irq_handler() {
112+
println!("> IRQ");
113+
while let Some(int_id) = GicCpuInterface::get_and_acknowledge_interrupt(InterruptGroup::Group1)
114+
{
115+
// let's go re-entrant
116+
unsafe {
117+
cortex_ar::interrupt::enable();
118+
}
119+
println!("- IRQ Handling {:?}", int_id);
120+
match int_id {
121+
SGI_INTID_HI => high_prio(),
122+
SGI_INTID_LO => low_prio(),
123+
_ => unreachable!("We handle all enabled IRQs"),
124+
}
125+
// turn interrupts off again
126+
cortex_ar::interrupt::disable();
127+
GicCpuInterface::end_interrupt(int_id, InterruptGroup::Group1);
128+
}
129+
println!("< IRQ");
130+
}
131+
132+
/// High prio IRQ
133+
fn high_prio() {
134+
println!(" - High prio!");
135+
}
136+
137+
/// Low prio IRQ
138+
fn low_prio() {
139+
println!(" - Low prio!");
140+
141+
priority_ceiling_lock(|| {
142+
GicCpuInterface::send_sgi(
143+
SGI_INTID_HI,
144+
SgiTarget::List {
145+
affinity3: 0,
146+
affinity2: 0,
147+
affinity1: 0,
148+
target_list: 0b1,
149+
},
150+
SgiTargetGroup::CurrentGroup1,
151+
)
152+
.unwrap();
153+
println!(" - Pre lock exit");
154+
println!(" - HIGH PRIO SHOULD RUN AFTER THIS");
155+
});
156+
println!(" - HIGH PRIO SHOULD RUN BEFORE THIS");
157+
println!(" - Post lock exit");
158+
}
159+
160+
fn priority_ceiling_lock<F: FnMut()>(mut f: F) {
161+
let prio = GicCpuInterface::get_priority_mask();
162+
// Block everything up to, and including, `HIGH_PRIORITY`
163+
GicCpuInterface::set_priority_mask(HIGH_PRIORITY);
164+
165+
f();
166+
167+
GicCpuInterface::set_priority_mask(prio);
168+
}

0 commit comments

Comments
 (0)