You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. You might not be preserving/restoring registers correctly: In MIPS, $a0-$a3 are caller-saved registers. If you modify $a1 in 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.
  2. Your timer interrupt isn't checking $a1 properly: The key handler sets $a1 to 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 eret to exit an interrupt handler, not jr $ra. eret restores the CP0 Status register and re-enables interrupts, whereas jr $ra will 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:29:37