📄 cpu_support.s
字号:
ldrb r1, [r1]
ldr r0, [r0, r1, asl #2]
bx r0
//////////////////////////////////////////////////////////////////////////////////////////////////////
// pre_idle:
// switch the stack from a task stack to the "system_stack"
// callevel = TCL_ISR2 (type2 interrupt level)
// fall to idle_loop
///////////////////////////////////////////////////////////////////////////////////////////////////////
pre_idle:
ldr sp, =__system_stack__
bic sp, sp, #7 // make sure it is 8-byte aligned
ldr r0, =callevel
mov r1, #TCL_ISR2
strb r1, [r0]
// fall to idle_loop
///////////////////////////////////////////////////////////////////////////////////////////////////////
// idle_loop:
// the body of the idle task
// enable interrupt
// wait for a while (wait for an interrupt to arrive)
// disable interupt
// if (schedtsk == INVALID) jump back to "idle_loop"
// callevel = TCS_TASK
// jump to "start_dispatch"
///////////////////////////////////////////////////////////////////////////////////////////////////////
idle_loop:
msr cpsr, #0x5F // enable interrupt
b next1 // wait for a while
next1:
b next2
next2:
b next3
next3:
msr cpsr, #0xDF // disable interrupt
mov r0, #INVALID_TASK // if (schedtsk == INVALID) jump back to "idle_loop"
ldr r1, =schedtsk
ldrb r1, [r1]
cmp r0, r1
beq idle_loop
mov r0, #TCL_TASK // callevel = TCL_TASK
ldr r1, =callevel
strb r0, [r1]
b start_dispatch // jump to "start_dispatch"
/////////////////////////////////////////////////////////////////////////////////////////////////
// ret_int:
// when an interrupt handler finds relation (runtsk != schedtsk) right before
// it returns (that is, the scheduler has run in the execution
// of the C handler), it jumps to this function, instead of returing to
// the interrupted context
// precondition: the destructive registers of the old task have been saved
// save the non-destructive registers
// save sp in the sp saving area in the old task's TCB
// save "ret_int_r" in the pc saving area in the old task's TCB
// jump to "dispatcher"
///////////////////////////////////////////////////////////////////////////////////////////////////
ret_int:
stmfd sp!, {r4-r7} // save remaining nondestructive regs
ldr r0, =runtsk // tcxb_sp[runtsk] = sp
ldrb r0, [r0]
ldr r1, =tcxb_sp
str sp, [r1, r0, asl #2]
ldr r1, =tcxb_pc // tcxb_pc[runtsk] = "ret_int_r"
ldr r2, =ret_int_r
str r2, [r1, r0, asl #2]
b dispatcher // jump to "dispatcher"
//////////////////////////////////////////////////////////////////////////////////////////////////
// ret_int_r:
// If a task is preempted in an interrupt handler (e.g., the handler
// called SetResource to awaken a higher priority task),
// the task starts with this function when it is scheduled again
// restore the non-destructive registers
// jump to "int_return"
//////////////////////////////////////////////////////////////////////////////////////////////////
ret_int_r:
ldmfd sp!, {r4-r7} // restore non destructive registers
b int_return
///////////////////////////////////////////////////////////////////////////////////////////////////
// _interrupt:
// this is called from macro "irq_wrapper_type2"
// the following registers hold the context values
// r8: runisr of the interrupted context
// r9: sp of the interrupted context
// r10: callevel of the interrupted context
// r11: the address of the high-level (in C) interrupt handler to call
// if (callevel == TCL_TASK) {
// // this interrupt arrives when a task (or a task + (type1 int)* ) run
// save sp in r9 and set sp to the bottom of the system stack
// }
// /*fall to "int_from_int"*/
//////////////////////////////////////////////////////////////////////////////////////////////////////
_interrupt:
ldr r1, =callevel
ldrb r1, [r1]
cmp r1, #TCL_TASK
bne int_from_int
mov r9, sp // save sp in r9
ldr sp, =__system_stack__
bic sp, sp, #7
//////////////////////////////////////////////////////////////////////////////////////////////////////
// int_from_int:
// it calls C function
// save callevel in r10 and update callevel to TCL_ISR2
// enable interrupt
// call the C function
// disable interrupt
// restore callevel
// restore runisr
// if (restored callevel == TCL_TASK) {
// restore sp from r9
// if (shcedtsk != runtsk) goto "ret_int"
// }
// // fall to int_return
/////////////////////////////////////////////////////////////////////////////////////////////////////
int_from_int:
mov r10, r1 // save call level in r10
ldr r1, =callevel // update callevel to TCL_ISR2
mov r2, #TCL_ISR2
strb r2, [r1]
msr cpsr, #0X5F // enable int
mov lr, pc
bx r11 // call C function
msr cpsr, #0XDF // disable int
ldr r1, =callevel // restore call level
strb r10, [r1]
ldr r2, =runisr
strb r8, [r2] // restore runisr
cmp r10, #TCL_TASK
bne int_return
mov sp, r9 // restore stack pointer
ldr r0, =schedtsk
ldrb r0, [r0]
ldr r1, =runtsk
ldrb r1, [r1]
cmp r0, r1
bne ret_int
// fall to int_return
//////////////////////////////////////////////////////////////////////////////////////////////////////
// int_return:
// restore destructive and context value holding registers and
// return from the interrupt
// write to AIC_EOICR (?? just following the leJos convention)
// get saved spsr and lr from the system stack
// push the recovered spsr and lr onto the irq stack
// restore destructive and context value holding registers
// return from the interrupt
///////////////////////////////////////////////////////////////////////////////////////////////////////
int_return:
@ end of interrupt by doing a write to AIC_EOICR
@ just following the leJos convention
ldr r0, =0xFFFFF130
str r0, [r0]
@get spsr and lr in r0, r1
ldmfd sp!, {r0-r1}
@switch to irq stack and save spsr and lr there
msr cpsr, #0XD2
stmfd sp!, {r0-r1}
@switch back to system stack and restore registers
msr cpsr, #0XDF
ldmfd sp!, {r0-r3,r8-r11, ip, lr}
@switch back to irq stack and return from interrupt
msr cpsr, #0XD2
ldmfd sp!, {r14} @restore spsr
msr spsr, r14
ldmfd sp!, {pc}^ @restore pc (lr value) and cpsr (spsr value)
@ that is, return from interrupt
disable_int:
msr cpsr, #0xDF
bx lr
enable_int:
msr cpsr, #0x5F
bx lr
nop:
bx lr
/* 掕悢偺掕媊 */
.equ TCL_TASK , 1
.equ TCL_ISR2 , 2
.equ INVALID_TASK, 0xFF
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -