问题
So I'm having trouble figuring out how to trigger a Timer interrupt (Every 200 cycles) and a button interrupt. When I hit the button interrupt all it seems to do is temporarily pause the counter for a split second and then continue counting. Then it never registers another button interrupt no matter how often I click it on PLP. What the button interrupt is suppose to do is set the register $a1 to 1 (or a non zero number) which is suppose to reset the counter. The Timer interrupt is suppose to flash the LEDs on every 200 cycles and then off after another 200 cycles and so forth. The seven segment display code is already provided for so what it does is just count up from 0-9 then A-F, and then starts over with the 10s. So 11, 12, ... , 19, 1A, 1B, ... , 1F, 20, etc.
.org 0x10000000
li $sp, 0x10fffffc # Stack pointer initialization
li $s0, sseg_lut # Lookup table address used by sseg_display
lui $s1, 0xf070 # Interrupt controller register
lui $s2, 0xf0a0 # Seven segment display
# TODO: enable interrupts here:
# ************************************************************
# Interrupt Initialization
li $t2, 0b1011 #value used to enable the used interrupts
li $t4, 0b00000000 #value used to check if LEDs are off
li $t5, 0b11111111 #value used to check if LEDs are on
li $t6, 0xf0600000 #address of the Timer
li $t7, 0xC8 #number of cycles we want the timer interrupt to be triggered
sw $t7, 0($t6) #Store value onto timer in order to trigger interrupt????????????????
li $t8, 0xf0200000 #address of LEDs
sw $t2, 0($s1) #set mask register to enable the used interrupts including Global Interrupt Enable
li $iv, isr #interrupt vector
# ************************************************************
main:
jal sseg_display
nop
addiu $a0, $a0, 1
beq $a1, $0, no_counter_reset
nop
move $a0, $0
move $a1, $0
no_counter_reset:
j main
nop
# TODO: add interrupt service routine here:
# ************************************************************
# Interrupt Service Routine
isr:
save
li $t0, 0b0011 #value used to check for timer interrupt
li $t1, 0b1001 #value used to check for button interrupt
lw $i0, 0($t8) #check what is stored currently on LEDs
lw $i1, 4($s1) #load what value is in the status register
j mainISR
nop
mainISR:
beq $i1, $t0, timerInterrupt #check if the interrupt was triggered by timer
nop
beq $i1, $t1, buttonInterrupt #check if interrupt was triggered by button
nop
timerInterrupt:
beq $t4, $i0, turnOnLEDs #If the LEDs are off, go to the loop to turn them on
nop
bne $t4, $i0, turnOffLEDs #If the LEDs are on, go to the loop to turn them off
nop
turnOnLEDs:
sw $t5, 0($t8) #Stores the value to the LEDs to turn them all on
li $i1, 0b1001 #Bits used to clear interrupt in status register
j endISR #Jump to the end of the isr
nop
turnOffLEDs:
sw $t4, 0($t8) #Stores the value to the LEDs to turn them all off
li $i1, 0b1001 #Bits used to clear interrup in status register
j endISR #Jump to the end of the isr
nop
buttonInterrupt:
li $a1, 1 #Set $a1 to 1, per the instructions to reset counter
li $i1, 0b0011 #Bits used to clear interrupt in status register
j endISR #Jump to end of isr
nop
j mainISR #possibly unnecessary isr loop
nop
endISR:
sw $i1, 4($s1) #clear handled interrupts
lw $i1, 0($s1) #get the mask register
ori $i1, $i1, 1 #set Global Interrupt Enable
restore
jr $ir
sw $i1, 0($s1) #resets all interrupts
# ************************************************************
回答1:
The timer triggers when overflow occurs. It is 32 bit timer so when you go past value 0xffff ffff your isr will be called.
The way to do it for 0xC8 cycles is
li $t7,0xffff ffff
li $t8,0xC8
subu $t7,$t7,$t8
sw $t7,0($t6)
来源:https://stackoverflow.com/questions/49603851/plp-timer-and-button-interrupt-service-routine