arm9-rtos的中断汇编代码分析helper2416-rawos

//zz//##############################################################################
///### arm9-rtos的中断汇编代码分析
helper2416-rawos

///###
@2014-8-2 23:22:38
///###
REF:
raw-os-helper2416-master.zip

1.

在Helper2416的rawos的Keil工程中,IRQ中断入口函数的汇编代码分析


先看 Start.s 启动文件的代码,看到如下这段

exception_vector;

LDR PC,=reset_exception_process;//复位异常
LDR PC,=Undef_exception_process_asm;//未定义指令异常
LDR PC,=SWI_exception_process;//软中断异常
LDR PC,=Pabort_exception_process;//取指中止异常
LDR PC,=Dabort_exception_process;//数据中止异常
LDR PC,. ;//保留
LDR PC,=raw_os_interrupt;//zz// IRQ中断异常for raw-os
LDR PC,=FIQ_exception_process;//FIQ中断异常

以后再搞明白 exception_vector 是怎么被设置/调用的吧,如上这些都是给PC赋值,跳转到相应的中断函数中去

raw_os_interrupt这个是IRQ中断的总入口(EINT? 定时器等中断都从这里进入)


今天只分析 raw_os_interrupt 汇编代码做了些什么

切换任务task,执行EINT?等中断ISR,跳回IRQ中断前的Context继续执行


raw_os_interrupt
	;//zz// irq 的堆栈sp上压栈R1-R3
	STMFD   SP!, {R1-R3}			; We will use R1-R3 as temporary registers

	;//zz// R1指向压栈后的堆栈地址
	MOV     R1, SP

	;//zz// SP指向加12/4=3,irq的堆栈回到压R1-R3之前
	ADD     SP, SP, #12             ;Adjust IRQ stack pointer

	;//zz// 3级流水线,中断前LR=PC指向了EXEC+8处(下两条),而LR需要是EXEC+4(下一条指令)
	SUB     R2, LR, #4              ;Adjust PC for return address to task

	MRS     R3, SPSR				; Copy SPSR (Task CPSR)

;##############################################################
	;//zz//切到SVC模式,SP(R13),LR(R14)及CPSR都是SVC模式下的了
	MSR     CPSR_cxsf, #SVCMODE:OR:NOINT   ;Change to SVC mode
	<span style="white-space:pre">	</span>; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK

	;//zz//将IRQ中断前打断的PC(LR=>R2),存到SVC做的堆栈里面来
	STMFD   SP!, {R2}				; Push task''s PC 
	STMFD   SP!, {R4-R12, LR}		; Push task''s LR,R12-R4

	;//zz//以R1为堆栈指针,出栈之前存的R1-R3
	LDMFD   R1!, {R4-R6}			; Load Task''s R1-R3 from IRQ stack 
	;//zz//再把进IRQ中断前的现场R1-R3压入R1-R3
	STMFD   SP!, {R4-R6}			; Push Task''s R1-R3 to SVC stack
	STMFD   SP!, {R0}			    ; Push Task''s R0 to SVC stack
	
	;//zz//压入CPSR(SVC模式之前存到R3中的)
	STMFD   SP!, {R3}				; Push task''s CPSR

	;//zz// 切换任务(其实就是换SP的值到指定的任务去)
	LDR     R4,=raw_task_active            
	LDR     R5,[R4]
	STR     SP,[R5] 

	;//zz//检测当前task的SP是否有效
	PUSH    {R14}
	bl      raw_stack_check
	POP     {R14}
	
	BL raw_enter_interrupt	

	;//zz// 切到IRQ模式下,完成ISR中断服务函数的调用	
	MSR    CPSR_c,#IRQMODE:OR:NOINT    ;Change to IRQ mode to use IRQ stack to handle interrupt
	BL      irq_process

<span style="white-space:pre">	</span>MSR		CPSR_c,#SVCMODE:OR:NOINT   ;Change to SVC mode

<span style="white-space:pre">	</span>BL raw_finish_int

<span style="white-space:pre">	</span>//zz// 弹出CPSR-PC,回到进入IRQ前保存的中断现场
<span style="white-space:pre">	</span>LDMFD   SP!,{R4}               ;POP the task''s CPSR 
<span style="white-space:pre">	</span>MSR		SPSR_cxsf,R4
<span style="white-space:pre">	</span>LDMFD   SP!,{R0-R12,LR,PC}^	   ;POP new Task''s context

2.

关于中断现场Context,堆栈SP的内存结构,具体参看 port.c 下的函数port_stack_init()

RAW_VOID  *port_stack_init(PORT_STACK  *p_stk_base,
<span style="white-space:pre">		</span>RAW_U32 stk_size,
<span style="white-space:pre">		</span>RAW_VOID   *p_arg,
<strong></strong><pre name="code" class="cpp" style="display: inline !important; "><span style="white-space:pre">		</span>RAW_TASK_ENTRY p_task)

 
{
	RAW_U32 *stk;
	RAW_U32 temp = (RAW_U32)(p_stk_base + stk_size - 4);
	stk = (RAW_U32  *)temp;
	                                       
	*(stk)    = (RAW_U32)p_task;       /* Entry Point PC R15*/
<span style="white-space:pre">	</span>//zz// R14 is just SP...
	*(--stk)  = (RAW_U32)0;             /* LR R14*/
	*(--stk)  = (RAW_U32)0;             /* R12 */
	*(--stk)  = (RAW_U32)0;             /* R11 */
	*(--stk)  = (RAW_U32)0;             /* R10 */
	*(--stk)  = (RAW_U32)0;             /* R9 */
	*(--stk)  = (RAW_U32)0;             /* R8 */
	*(--stk)  = (RAW_U32)0;             /* R7 */
	*(--stk)  = (RAW_U32)0;             /* R6 */
	*(--stk)  = (RAW_U32)0;             /* R5 */
	*(--stk)  = (RAW_U32)0;             /* R4 */
	*(--stk)  = (RAW_U32)0;             /* R3 */
	*(--stk)  = (RAW_U32)0;             /* R2 */
	*(--stk)  = (RAW_U32)0;             /* R1 */
	*(--stk)  = (RAW_U32)p_arg;         /* R0 argument */
	*(--stk)  = (RAW_U32)0x13;<span style="white-space:pre">	</span>/* CPSR SVC mode */
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return stk;
}
push压栈的顺序是: 

高地址 PC => LR =>  R12 ... R1 => R0 => CPSR 低地址

pop出栈的顺序是(从内存地址来看是一样的):

低地址 CPSR => R0 => R1 ... R12 => LR => PC 高地址


3.

其他几段汇编代码在对 2. 中栈的结构有了解后,就很好理解了..

port_task_switch //任务切换

raw_int_switch//rawos开机启动最高优先级任务

OS_CPU_SR_Save//CPSR状态寄存器保存,之后关闭中断

OS_CPU_SR_Restore//CPSR状态寄存器恢复(是否恢复中断使能,要看Save保存的什么值)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值