summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-05-27 12:21:32 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-05-27 12:21:32 +0000
commit139e6efe3ca838f1889322f4bed2bbe926ccbb89 (patch)
tree58d93213e3ab55b9996d093787c83e24c994112c /c/src/exec/score/cpu
parentChanged process group routines to unimplementable. (diff)
downloadrtems-139e6efe3ca838f1889322f4bed2bbe926ccbb89.tar.bz2
Fix from Jiri Gaisler <jgais@ws.estec.esa.nl> for a problem in which
external interrupt priorities were not being honored. Here is some of his original report: using rtems/erc32, I have a problem with interrupt priority when interrupts occure simultaneously. Erc32 has an interrupt force register where interrupts can be generated. If more than one interrupt is generated, the interrupt handlers are scheduled in the wrong order, i.e. with the lowest priority first. I have attched a program that generates three interrupts, 0x11, 0x12 and 0x13. Interrupt 0x13 should be handled first, but is actually handled last. Below is the output from sis: sis> go resuming at 0x02000000 RAM size: 4096 K, ROM size: 2048 K Watchdog disabled Waitstates = RAM read: 0, RAM write: 0, ROM read: 0, ROM write: 0 Power-down mode enabled infinite UART baudrate External interrupt received with vector 0x11 External interrupt received with vector 0x12 External interrupt received with vector 0x13 I have verified that sis generates the interrupts in the correct order, i.e. 0x13 first, then 0x12 and then 0x11. So the problem seems to be in the rtems interrupt handler. Do you use the PIL field in the %psr register to mask lower priority interrupts or are all external interrupts considered to have the same priority ..? Here is a description of the fix: it turned out that lower priority interrupts were not at all masked off during interrupt handling. I made the following fix to cpu_asm.s: ... fix is in the code ... There might be a simpler way of doing this, but this works...
Diffstat (limited to 'c/src/exec/score/cpu')
-rw-r--r--c/src/exec/score/cpu/sparc/cpu_asm.s19
1 files changed, 18 insertions, 1 deletions
diff --git a/c/src/exec/score/cpu/sparc/cpu_asm.s b/c/src/exec/score/cpu/sparc/cpu_asm.s
index d9af28e19e..2376ea53bf 100644
--- a/c/src/exec/score/cpu/sparc/cpu_asm.s
+++ b/c/src/exec/score/cpu/sparc/cpu_asm.s
@@ -489,7 +489,24 @@ dont_switch_stacks:
sub %sp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp
- wr %l0, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
+ /*
+ * Check if we have an external interrupt (trap 0x11 - 0x1f). If so,
+ * set the PIL in the %psr to mask off interrupts with lower priority.
+ * The original %psr in %l0 is not modified since it will be restored
+ * when the interrupt handler returns.
+ */
+
+ mov %l0, %g5
+ subcc %l3, 0x11, %g0
+ bl dont_fix_pil
+ subcc %l3, 0x1f, %g0
+ bg dont_fix_pil
+ sll %l3, 8, %g4
+ and %g4, SPARC_PSR_PIL_MASK, %g4
+ andn %l0, SPARC_PSR_PIL_MASK, %g5
+ or %g4, %g5, %g5
+dont_fix_pil:
+ wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
/*
* Vector to user's handler.