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

如何解决RARS中Digital Lab Sim运行冻结问题?

RARS使用Digital Lab Sim(DLS)十六进制键盘时频繁冻结的问题排查与优化

我正在学习RISC-V,使用RARS及其内置的Digital Lab Sim(DLS)模拟设备实现十六进制键盘按键读取功能,但RARS仅运行几次就会冻结,必须重启。试过增加延迟时长、降低程序运行速度,均无效果。以下是我的实现代码:

.eqv IN_ADDRESS_HEXA_KEYBOARD 0xFFFF0012
.eqv OUT_ADDRESS_HEXA_KEYBOARD 0xFFFF0014
.data
    message: .asciz "Key scan code: "
# -----------------------------------------------------------------
# MAIN Procedure
# -----------------------------------------------------------------
.macro checkKeyCode(%registor, %value, %ascii)
    li t0, %value
    bne t0, %registor, skip
    li s6, %ascii
skip:
.end_macro

.text
main:
# Load the interrupt service routine address to the UTVEC register
    la t0, handler
    csrrs zero, utvec, t0
# Set the UEIE (User External Interrupt Enable) bit in UIE register
    li t1, 0x100
    csrrs zero, uie, t1 # uie - ueie bit (bit 8)
# Set the UIE (User Interrupt Enable) bit in USTATUS register
    csrrsi zero, ustatus, 0x1 # ustatus - enable uie (bit 0)
# Enable the interrupt of keypad of Digital Lab Sim
    li t1, IN_ADDRESS_HEXA_KEYBOARD
    li t3, 0x80 # bit 7 = 1 to enable interrupt 
    sb t3, 0(t1)
# ---------------------------------------------------------
# Loop to print a sequence of numbers
# ---------------------------------------------------------
    xor s0, s0, s0 # count = s0 = 0
loop: 
    addi s0, s0, 1 # count = count + 1
prn_seq:
    addi a7, zero, 1
    add a0, s0, zero # Print auto sequence number 
    ecall
    addi a7, zero, 11
    li a0, '\n' # Print EOL
    ecall
sleep:
    addi a7, zero, 32
    li a0, 5000 # Sleep 300 ms
    ecall
    j loop
end_main:
# -----------------------------------------------------------------
# Interrupt service routine
# -----------------------------------------------------------------
handler:
# Saves the context
    addi sp, sp, -16
    sw a0, 0(sp)
    sw a7, 4(sp)
    sw t1, 8(sp)
    sw t2, 12(sp)
# Handles the interrupt
prn_msg:
    addi a7, zero, 4
    la a0, message
    ecall
load_all_rows:
    li t1, IN_ADDRESS_HEXA_KEYBOARD
    li t2, OUT_ADDRESS_HEXA_KEYBOARD
    li t3, 0x1 # Start from Row 1
    li t4, 0x8 # Row 4 (maximum row)
scan_rows:
    addi t5, t3, 0x80
    sb t5, 0(t1) # Write Row (Row n) to IN_ADDRESS
    lb a0, 0(t2) # Read key scan code from OUT_ADDRESS
    beqz a0, next_row # If no key pressed, move to the next row
    # Handle key press (print scan code)
checkkeyCode:
    checkKeyCode(a0, 0x11, 0x30)
    checkKeyCode(a0, 0x21, 0x31)
    checkKeyCode(a0, 0x41, 0x32)
    checkKeyCode(a0, 0x81, 0x33)
    
    checkKeyCode(a0, 0x12, 0x34)
    checkKeyCode(a0, 0x22, 0x35)
    checkKeyCode(a0, 0x42, 0x36)
    checkKeyCode(a0, 0x82, 0x37)

    checkKeyCode(a0, 0x14, 0x38)
    checkKeyCode(a0, 0x24, 0x39)
    checkKeyCode(a0, 0x44, 0x61)
    checkKeyCode(a0, 0x84, 0x62)

    checkKeyCode(a0, 0x18, 0x63)
    checkKeyCode(a0, 0x28, 0x64)
    checkKeyCode(a0, 0x48, 0x65)
    checkKeyCode(a0, 0x88, 0x66)

next_row:
    slli t3, t3, 1 # Shift left to move to the next row
    ble t3, t4, scan_rows # Repeat for Row 4
     
prn_key_code:
    mv a0, s6
    li a7, 11
    ecall
# Restores the context
    lw t2, 12(sp)
    lw t1, 8(sp)
    lw a7, 4(sp)
    lw a0, 0(sp)
    addi sp, sp, 16
# Back to the main procedure
    uret

问题根源分析

1. 代码层面问题

  • 上下文保存不完整:中断服务程序(ISR)中修改了s6寄存器,但未将其保存到栈中,会破坏主程序的s6状态,导致程序逻辑混乱甚至崩溃。
  • 中断标志未清除:DLS键盘触发中断后,未手动清除中断标志,会导致中断持续触发,CPU被中断完全占用,出现假死。
  • 宏标签冲突:checkKeyCode宏中的skip标签会在多次展开后重复,导致跳转逻辑错误,执行流程混乱。
  • 无中断嵌套防护:ISR执行期间未关闭外部中断,可能触发嵌套中断,导致栈溢出。

2. 模拟层面问题

  • RARS的DLS模拟存在已知的稳定性bug,频繁触发外部中断时容易出现死锁。
  • 模拟设备的中断触发速率过高,事件队列堆积导致冻结。

解决建议与优化方案

代码修复

  1. 完善上下文保存:在ISR中保存并恢复所有被修改的寄存器,包括s6:

    handler:
    # 扩展栈空间以保存s6
    addi sp, sp, -20
    sw a0, 0(sp)
    sw a7, 4(sp)
    sw t1, 8(sp)
    sw t2, 12(sp)
    sw s6, 16(sp)  # 保存s6
    
    # ... 原有处理逻辑 ...
    
    # 恢复s6
    lw s6, 16(sp)
    lw t2, 12(sp)
    lw t1, 8(sp)
    lw a7, 4(sp)
    lw a0, 0(sp)
    addi sp, sp, 20
    
  2. 清除中断标志:读取按键后,向键盘输入地址重新写入使能值以清除中断:

    # 在处理完按键后添加
    sb t5, 0(t1)  # 重新写入行选择+使能位,清除中断标志
    
  3. 修复宏标签冲突:给宏的跳转标签添加唯一后缀,避免重复:

    .macro checkKeyCode(%reg, %val, %ascii, %skip_label)
        li t0, %val
        bne t0, %reg, %skip_label
        li s6, %ascii
    %skip_label:
    .end_macro
    
    # 调用示例
    checkKeyCode(a0, 0x11, 0x30, skip_1)
    checkKeyCode(a0, 0x21, 0x31, skip_2)
    
  4. 添加中断嵌套防护:ISR执行期间临时关闭外部中断,执行完成后恢复:

    handler:
    # 临时关闭UEIE中断
    csrrc t0, uie, 0x100
    
    # ... 保存上下文与处理逻辑 ...
    
    # 恢复UEIE中断
    csrrs zero, uie, t0
    

RARS模拟优化

  • 只开启必要的模拟设备,关闭其他无关设备以降低负载。
  • 更新RARS至最新版本,修复已知的DLS稳定性bug。
  • 调整DLS键盘的防抖设置,减少误触发导致的频繁中断。

内容的提问来源于stack exchange,提问作者kiyoshi_akira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:48:11