📄 exceptions.s
字号:
.name "exceptions.s"
.import Rec_Buf
.section .abs.00000100
b _start ; System reset exception, per crt0 file
.section .abs.00000500
b external_interrupt_exception
.text
external_interrupt_exception:
.equ SIVEC, 0x2fc01c ; Register addresses
.equ SCI_BASE, 0x305000
.equ SC1SR, 0x30500c
.equ SC1DR, 0x30500e
; STEP 1: SAVE "MACHINE CONTEXT"
stwu sp, -36 (sp); Create stack frame and store back chain
stw r3, 24 (sp) ; Save working register
mfsrr0 r3 ; Get SRR0
stw r3, 12 (sp) ; and save SRR0
mfsrr1 r3 ; Get SRR1
stw r3, 16 (sp) ; and save SRR1
; STEP 2: MAKE MSR[RI] RECOVERABLE
mtspr EID, r3 ; Set recoverable bit
; Now debugger breakpoints can be set
; STEP 3: SAVE OTHER APPROPRIATE CONTEXT
mflr r3 ; Get LR
stw r3, 8 (sp) ; and save LR
mfcr r3 ; Get CR
stw r3, 20 (sp) ; and save CR
stw r4, 28 (sp) ; Save R4 to R6
stw r5, 32 (sp)
stw r6, 36 (sp)
; STEP 4: DETERMINE INTERRUPT SOURCE
lis r3, SIVEC@ha ; Load higher 16 bits of SIVEC address
lbz r3, SIVEC@l (r3) ; Load Interrupt Code byte from SIVEC
; Interrupt Code will be jump table index
lis r4, IRQ_table@h ; Load interrupt jump table base address
ori r4, r4, IRQ_table@l
add r4, r3, r4 ; Add index to table base address
mtlr r4 ; Load result address to link register
; STEP 5: BRANCH TO INTERRUPT HANDLER
blrl ; Jump to Execution Routine (subroutine)
; (After returning here, restore context)
; STEP 6: RESTORE CONTEXT
lwz r4, 28 (sp) ; Restore gprs except R3
lwz r5, 32 (sp)
lwz r6, 36 (sp)
lwz r3, 28 (sp) ; Get CR
mtcrf 0xff, r3 ; and restore CR
lwz r3, 20 (sp) ; Get LR
mtlr r3 ; and restore LR
mtspr NRI, r3 ; Clear recoverable bit, MSR[RI]
; Note: breakpoints CANNOT be set
; from now thru the rfi instruction
lwz r3, 12 (sp) ; Get SRR0 from stack
mtsrr0 r3 ; and restore SRR0
lwz r3, 16 (sp) ; Get SRR1 from stack
mtsrr1 r3 ; and restore SRR1
lwz r3, 24 (sp) ; Restore R3
addi sp, sp, 36 ; Restore stack
; STEP 7: Return to Program
rfi ; End of Interrupt
; ===================================================================
; Branch table for the different SIVEC Interrupt Code values:
IRQ_table: ; Branch forever if routine is not written
irq_0: b irq_0
level_0: b level_0
irq_1: b irq_1
level_1: b level_1
irq_2: b irq_2
level_2: b level_2
irq_3: b irq_3
level_3: b level_3
irq_4: b irq_4
level_4: b level_4
irq_5: b irq_5
b SCI_Int ; Branch to SCI assembler routine
irq_6: b irq_6
level_6: b level_6
irq_7: b irq_7
level_7: b level_7
; ===================================================================
; SCI interrupt service routine
SCI_Int:
lis r3, SCI_BASE@ha ; Load upper 16 bits of pointer to SCI
lhz r4, SC1SR@l (r3) ; Read status register
andi. r4, r4, 0x40 ; Test RDRF bit
beq SCI_transmit_int ; If RDRF not set, IRQ is a transmit
; Service receive IRQ:
lhz r4, SC1DR@l (r3) ; Read data from SCI,
; which automatically clears RDRF
lis r3, Rec_Buf@h ; Store data in buffer
ori r3, r3, Rec_Buf@l
; Prepare pointer to the buffer descriptor
lwz r5, 0 (r3) ; Load buffer pointer from buf. descriptor
lwz r6, 8 (r3) ; Load actual index
stbx r4, r6, r5 ; Put data into bufer
addi r6, r6, 1 ; Update index
lwz r5, 4 (r3) ; Get buffer size
cmp r5, r6
bne receive_buffer_not_full
; End of buffer reached, due to
; ringbuffer start at offset 0 again
li r6, 0 ; Get '0'
receive_buffer_not_full:
stw r6, 8 (r3) ; Store current index
SCI_transmit_int: ; (TX interrupt not implemented)
blr ; Finished, return to main IRQ handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -