Skip to content

Commit 62ae2ff

Browse files
committed
The IRQ handler needs to save LR.
Now the re-entrant test works correctly.
1 parent 1e002a2 commit 62ae2ff

File tree

4 files changed

+57
-25
lines changed

4 files changed

+57
-25
lines changed

cortex-a-rt/src/lib.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ pub extern "C" fn _default_handler() {
339339
core::arch::global_asm!(
340340
r#"
341341
.section .vector_table,"ax",%progbits
342-
343342
.global _vector_table
344343
.type _vector_table, %function
345344
_vector_table:
@@ -502,19 +501,19 @@ macro_rules! restore_context {
502501
// Our assembly language exception handlers
503502
core::arch::global_asm!(
504503
r#"
505-
.section .text._asm_default_undefined_handler
506-
504+
507505
// Called from the vector table when we have an undefined exception.
508506
// Saves state and calls a C-compatible handler like
509507
// `extern "C" fn _undefined_handler(addr: usize) -> usize;`
510508
// or
511509
// `extern "C" fn _undefined_handler(addr: usize) -> !;`
510+
.section .text._asm_default_undefined_handler
512511
.global _asm_default_undefined_handler
513512
.type _asm_default_undefined_handler, %function
514513
_asm_default_undefined_handler:
515514
// state save from compiled code
516-
srsfd sp!, {und_mode}
517-
// to work out what mode we're in, we need R0, so save it
515+
srsfd sp!, #{und_mode}
516+
// to work out what mode we're in, we need R0
518517
push {{r0}}
519518
// First adjust LR for two purposes: Passing the faulting instruction to the C handler,
520519
// and to return to the failing instruction after the C handler returns.
@@ -548,7 +547,7 @@ core::arch::global_asm!(
548547
rfefd sp!
549548
.size _asm_default_undefined_handler, . - _asm_default_undefined_handler
550549
551-
550+
552551
.section .text._asm_default_svc_handler
553552
554553
// Called from the vector table when we have an software interrupt.
@@ -557,7 +556,7 @@ core::arch::global_asm!(
557556
.global _asm_default_svc_handler
558557
.type _asm_default_svc_handler, %function
559558
_asm_default_svc_handler:
560-
srsfd sp!, {svc_mode}
559+
srsfd sp!, #{svc_mode}
561560
"#,
562561
save_context!(),
563562
r#"
@@ -587,7 +586,7 @@ core::arch::global_asm!(
587586
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual.
588587
subs lr, lr, #8
589588
// state save from compiled code
590-
srsfd sp!, {abt_mode}
589+
srsfd sp!, #{abt_mode}
591590
"#,
592591
save_context!(),
593592
r#"
@@ -618,7 +617,7 @@ core::arch::global_asm!(
618617
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual.
619618
subs lr, lr, #4
620619
// state save from compiled code
621-
srsfd sp!, {abt_mode}
620+
srsfd sp!, #{abt_mode}
622621
"#,
623622
save_context!(),
624623
r#"
@@ -646,16 +645,28 @@ core::arch::global_asm!(
646645
.global _asm_default_irq_handler
647646
.type _asm_default_irq_handler, %function
648647
_asm_default_irq_handler:
648+
// make sure we jump back to the right place
649649
sub lr, lr, 4
650-
srsfd sp!, {irq_mode}
650+
// The hardware has copied CPSR to SPSR_irq and LR to LR_irq for us.
651+
// Now push SPSR_irq and LR_irq to the SYS stack.
652+
srsfd sp!, #{sys_mode}
653+
// switch to system mode
654+
cps #{sys_mode}
655+
// we also need to save LR, so we can be re-entrant
656+
push {{lr}}
657+
// save state to the system stack (adjusting SP for alignment)
651658
"#,
652-
save_context!(),
659+
save_context!(),
653660
r#"
654661
// call C handler
655662
bl _irq_handler
663+
// restore from the system stack
656664
"#,
657-
restore_context!(),
665+
restore_context!(),
658666
r#"
667+
// restore LR and the dummy value
668+
pop {{lr}}
669+
// pop CPSR and LR from the stack (which also restores the mode)
659670
rfefd sp!
660671
.size _asm_default_irq_handler, . - _asm_default_irq_handler
661672
@@ -670,9 +681,9 @@ core::arch::global_asm!(
670681
.size _asm_default_fiq_handler, . - _asm_default_fiq_handler
671682
"#,
672683
svc_mode = const ProcessorMode::Svc as u8,
673-
irq_mode = const ProcessorMode::Irq as u8,
674684
und_mode = const ProcessorMode::Und as u8,
675685
abt_mode = const ProcessorMode::Abt as u8,
686+
sys_mode = const ProcessorMode::Sys as u8,
676687
t_bit = const {
677688
Cpsr::new_with_raw_value(0)
678689
.with_t(true)

cortex-r-rt/src/lib.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ core::arch::global_asm!(
463463
.type _asm_default_undefined_handler, %function
464464
_asm_default_undefined_handler:
465465
// state save from compiled code
466-
srsfd sp!, {und_mode}
466+
srsfd sp!, #{und_mode}
467467
// to work out what mode we're in, we need R0
468468
push {{r0}}
469469
// First adjust LR for two purposes: Passing the faulting instruction to the C handler,
@@ -507,7 +507,7 @@ core::arch::global_asm!(
507507
.global _asm_default_svc_handler
508508
.type _asm_default_svc_handler, %function
509509
_asm_default_svc_handler:
510-
srsfd sp!, {svc_mode}
510+
srsfd sp!, #{svc_mode}
511511
"#,
512512
save_context!(),
513513
r#"
@@ -537,7 +537,7 @@ core::arch::global_asm!(
537537
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual.
538538
subs lr, lr, #8
539539
// state save from compiled code
540-
srsfd sp!, {abt_mode}
540+
srsfd sp!, #{abt_mode}
541541
"#,
542542
save_context!(),
543543
r#"
@@ -568,7 +568,7 @@ core::arch::global_asm!(
568568
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual.
569569
subs lr, lr, #4
570570
// state save from compiled code
571-
srsfd sp!, {abt_mode}
571+
srsfd sp!, #{abt_mode}
572572
"#,
573573
save_context!(),
574574
r#"
@@ -596,16 +596,28 @@ core::arch::global_asm!(
596596
.global _asm_default_irq_handler
597597
.type _asm_default_irq_handler, %function
598598
_asm_default_irq_handler:
599+
// make sure we jump back to the right place
599600
sub lr, lr, 4
600-
srsfd sp!, {irq_mode}
601+
// The hardware has copied CPSR to SPSR_irq and LR to LR_irq for us.
602+
// Now push SPSR_irq and LR_irq to the SYS stack.
603+
srsfd sp!, #{sys_mode}
604+
// switch to system mode
605+
cps #{sys_mode}
606+
// we also need to save LR, so we can be re-entrant
607+
push {{lr}}
608+
// save state to the system stack (adjusting SP for alignment)
601609
"#,
602-
save_context!(),
610+
save_context!(),
603611
r#"
604612
// call C handler
605613
bl _irq_handler
614+
// restore from the system stack
606615
"#,
607-
restore_context!(),
616+
restore_context!(),
608617
r#"
618+
// restore LR
619+
pop {{lr}}
620+
// pop CPSR and LR from the stack (which also restores the mode)
609621
rfefd sp!
610622
.size _asm_default_irq_handler, . - _asm_default_irq_handler
611623
@@ -620,9 +632,9 @@ core::arch::global_asm!(
620632
.size _asm_default_fiq_handler, . - _asm_default_fiq_handler
621633
"#,
622634
svc_mode = const ProcessorMode::Svc as u8,
623-
irq_mode = const ProcessorMode::Irq as u8,
624635
und_mode = const ProcessorMode::Und as u8,
625636
abt_mode = const ProcessorMode::Abt as u8,
637+
sys_mode = const ProcessorMode::Sys as u8,
626638
t_bit = const {
627639
Cpsr::new_with_raw_value(0)
628640
.with_t(true)
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
Found PERIPHBASE 0xf0000000
22
Creating GIC driver @ 0xf0000000 / 0xf0100000
33
Calling git.setup(0)
4-
Configure SGI...
4+
Configure low-prio SGI...
5+
Configure high-prio SGI...
56
gic.enable_interrupt()
67
Enabling interrupts...
78
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) }
89
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) }
9-
Send SGI
10+
Send lo-prio SGI
1011
> IRQ
11-
- IRQ handle SGI 3
12+
- IRQ Handling SGI 3
13+
- IRQ got SGI 3, sending hi-prio SGI 4
14+
> IRQ
15+
- IRQ Handling SGI 4
16+
< IRQ
17+
- IRQ finished sending hi-prio!
1218
< IRQ
19+
IRQ test completed OK

examples/mps3-an536/src/bin/gic.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ fn main() -> ! {
8484
cortex_ar::asm::nop();
8585
}
8686

87+
println!("IRQ test completed OK");
88+
8789
semihosting::process::exit(0);
8890
}
8991

@@ -100,7 +102,7 @@ fn irq_handler() {
100102
unsafe {
101103
cortex_ar::interrupt::enable();
102104
}
103-
println!("- IRQ Handing {:?}", int_id);
105+
println!("- IRQ Handling {:?}", int_id);
104106
if int_id == SGI_INTID_LO {
105107
println!(
106108
"- IRQ got {:?}, sending hi-prio {:?}",

0 commit comments

Comments
 (0)