PLP中定时器(每200周期)与按键中断异常问题求助
Alright, let's dig into what's going on with your PLP interrupt setup—this is a super common set of pitfalls when working with timer and GPIO interrupts on these platforms! Let's break down the issues and fix them step by step.
First: Why your key interrupt stops triggering after the first press
The #1 culprit here is almost always forgetting to clear the interrupt request flag on your key peripheral. Most PLP hardware (especially MIPS-based ones) sets a flag bit when a key press triggers an interrupt, and if you don't manually clear that flag, the hardware thinks the interrupt is still pending. This can either cause repeated spurious interrupts, or (like in your case) block all future interrupts from that peripheral because it thinks it's still handling the first one.
Fix this by adding flag-clearing code at the end of your key interrupt handler, right before you return with eret:
# Example: If your key IRQ flag register is at 0xffff0004, write 0 to clear it li $t0, 0xffff0004 sw $zero, 0($t0)
Double-check your PLP documentation for the exact address of your key module's interrupt flag register—this is non-negotiable for getting repeat interrupts.
Second: Why the counter only pauses briefly instead of resetting
That brief pause is just the CPU switching to run the key interrupt handler—once it returns, the timer interrupt picks back up like normal. The real issue is that your $a1 reset logic isn't actually working as intended, and here's why:
- You might not be preserving/restoring registers correctly: In MIPS,
$a0-$a3are caller-saved registers. If you modify$a1in your key interrupt handler without first saving its original value to the stack, you'll corrupt the value the main program (or timer interrupt) is using. Make sure your handler saves$a1(and any other registers you touch) at the start, then restores them before returning. - Your timer interrupt isn't checking
$a1properly: The key handler sets$a1to non-zero, but your timer handler needs explicit logic to catch that and reset the counter. For example:
# Inside your timer interrupt handler lw $t1, counter # Load current counter value bnez $a1, reset_count # If $a1 is non-zero, jump to reset logic addi $t1, $t1, 1 # Increment counter normally j update_counter reset_count: li $t1, 0 # Reset counter to 0 li $a1, 0 # Clear $a1 so we don't keep resetting every timer tick update_counter: sw $t1, counter # Save updated counter value
Without this check, modifying $a1 does nothing to the counter—it just keeps incrementing whenever the timer interrupt hits.
Quick sanity checks to rule out other issues
- Make sure you're returning from interrupts correctly: Always use
eretto exit an interrupt handler, notjr $ra.eretrestores the CP0 Status register and re-enables interrupts, whereasjr $rawill leave interrupts disabled and break all future interrupts. - Verify interrupt masking isn't getting messed up: Some PLP interrupt controllers auto-mask the triggering interrupt until you clear the flag, but if your code is accidentally setting a global mask bit, that could block all interrupts. Double-check that your Status register's IE (Interrupt Enable) bit stays set after interrupt returns.
内容的提问来源于stack exchange,提问作者JustWorkAlready

