⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu_support.s

📁 专业汽车级嵌入式操作系统OSEK的源代码
💻 S
📖 第 1 页 / 共 2 页
字号:
	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 + -