Chinaunix首页 | 论坛 | 博客
  • 博客访问: 432166
  • 博文数量: 103
  • 博客积分: 1455
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-15 22:17
文章分类

全部博文(103)

文章存档

2013年(4)

2012年(99)

我的朋友

分类: LINUX

2012-11-27 10:24:32

在μc/os中的OS_cpu_a.s中用汇编语言实现了一下函数,其中很多与硬件相关,如果要在不同的平台上面进行移植,要进行修改,准备将系统移植到我们的SHARC-DSP上面去试一试。下面的代码是ARM体系,吐槽一下CU的代码粘贴,对汇编的支持不够好啊。。

OSCtxSw()任务上下文切换, 将当前任务压栈,切换当前优先级和当前TCB,从新的TCB中弹栈

操作系统的核心

点击(此处)折叠或打开

  1. OSCtxSw
  2.   STMFD SP!, {LR} ;PC
  3.   STMFD SP!, {R0-R12, LR} ;R0-R12 LR
  4.   MRS R0, CPSR ;Push CPSR
  5.   STMFD SP!, {R0}
  6. ;----------------------------------------------------------------------------------
  7. ; OSTCBCur->OSTCBStkPtr = SP
  8. ;----------------------------------------------------------------------------------
  9.   LDR R0, =OSTCBCur
  10.   LDR R0, [R0]
  11.   STR SP, [R0]
  12. ;----------------------------------------------------------------------------------
  13. ; OSTaskSwHook();
  14. ;---------------------------------------------------------------------------------
  15.   BL OSTaskSwHook
  16. ;----------------------------------------------------------------------------------
  17. ; OSTCBCur = OSTCBHighRdy;
  18. ;----------------------------------------------------------------------------------
  19.   LDR R0, =OSTCBHighRdy
  20.   LDR R1, =OSTCBCur
  21.   LDR R0, [R0]
  22.   STR R0, [R1]
  23. ;----------------------------------------------------------------------------------
  24. ; OSPrioCur = OSPrioHighRdy;
  25. ;----------------------------------------------------------------------------------
  26.   LDR R0, =OSPrioHighRdy
  27.   LDR R1, =OSPrioCur
  28.   LDRB R0, [R0]
  29.   STRB R0, [R1]
  30. ;----------------------------------------------------------------------------------
  31. ; OSTCBHighRdy->OSTCBStkPtr;
  32. ;----------------------------------------------------------------------------------
  33.   LDR R0, =OSTCBHighRdy
  34.   LDR R0, [R0]
  35.   LDR SP, [R0]
  36. ;----------------------------------------------------------------------------------
  37. ;Restore New task context
  38. ;----------------------------------------------------------------------------------
  39.   LDMFD SP!, {R0} ;POP CPSR
  40.   MSR SPSR_cxsf, R0
  41.   LDMFD SP!, {R0-R12, LR, PC}^


 

OSIntCtxSw() 中断中实现task的上下文切换,与上一个函数不同的是不需要压栈,因为是在中断中的实现

OSStartHighRdy()OS开始运行时,切换进入第一个任务的服务子程序,不是中断

关中断 SVC模式 将OSRunning置1 SP(R13)切换到最高优先级任务的堆栈指针 弹栈

OS_CPU_IRQ_ISR() 这个程序在汇编boot文件中进行了调用,调用中断服务子程序对应的地址

所有的IRQ都要经过这个函数跳转到相应的中断向量表指向的子函数,这个函数在boot中被装入HandlerIRQ中

点击(此处)折叠或打开

  1. OS_CPU_IRQ_ISR
  2.   STMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registers
  3. ;----------------------------------------------------------------------------
  4. ; R1--SP
  5. ; R2--PC
  6. ; R3--SPSR
  7. ;------------------------------------------------------------------------
  8.   MOV R1, SP
  9.   ADD SP, SP, #12 ;Adjust IRQ stack pointer
  10.   SUB R2, LR, #4 ;Adjust PC for return address to task
  11.   MRS R3, SPSR ; Copy SPSR (Task CPSR)
  12.   MSR CPSR_cxsf, #SVCMODE|NOINT ;Change to SVC mode
  13. ; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
  14.   STMFD SP!, {R2} ; Push task''s PC
  15.   STMFD SP!, {R4-R12, LR} ; Push task''s LR,R12-R4
  16.   LDMFD R1!, {R4-R6} ; Load Task''s R1-R3 from IRQ stack
  17.   STMFD SP!, {R4-R6} ; Push Task''s R1-R3 to SVC stack
  18.   STMFD SP!, {R0} ; Push Task''s R0 to SVC stack
  19.   STMFD SP!, {R3} ; Push task''s CPSR
  20.   LDR R0,=OSIntNesting ;OSIntNesting++
  21.   LDRB R1,[R0]
  22.   ADD R1,R1,#1
  23.   STRB R1,[R0]
  24.   CMP R1,#1 ;if(OSIntNesting==1){
  25.   BNE %F1
  26.   LDR R4,=OSTCBCur ;OSTCBHighRdy->OSTCBStkPtr=SP;
  27.   LDR R5,[R4]
  28.   STR SP,[R5] ;}
  29. 1
  30.   MSR CPSR_c,#IRQMODE|NOINT ;Change to IRQ mode to use IRQ stack to handle interrupt
  31.   LDR R0, =INTOFFSET
  32.   LDR R0, [R0]
  33.   LDR R1, IRQIsrVect
  34.   MOV LR, PC ; Save LR befor jump to the C function we need return back
  35.   LDR PC, [R1, R0, LSL #2] ; Call OS_CPU_IRQ_ISR_handler();
  36.   MSR CPSR_c,#SVCMODE|NOINT ;Change to SVC mode
  37.   BL OSIntExit ;Call OSIntExit
  38.   LDMFD SP!,{R4} ;POP the task''s CPSR
  39.   MSR SPSR_cxsf,R4
  40.   LDMFD SP!,{R0-R12,LR,PC}^ ;POP new Task''s context

临时使用R1-R3作为SP PC SPSR寄存器

SVCmode 对于ARM来说,跳进中断模式会将PC值加4,即下一个指令地址赋值给LR,将LR-4会得到中断前PC的值
问题:利用ADD     SP, SP, #12 返回中断前的SP?进行压栈?

将R2 R4-R12 R14(LR)压入中断前任务的堆栈

从中断的堆栈取出数据到R4-R6 将R4-R6压栈如SVC栈,将R0压入SVC栈

OSIntNesting++ ;if(OSIntNesting==1){OSTCBHighRdy->OSTCBStkPtr=SP;}

进入IRQ模式,关中断,调用OS_CPU_IRQ_ISR_handler();

返回SVC模式,调用OSIntExit退出中断,中间使用了OSIntCtxSw()函数,判定OSIntNesting是否为0,如果中断有嵌套返回当前IRQ_ISR函数

从SP中弹栈返回进入中断前的上下文和SP LR

 

OSTickISR() 实现时钟滴答中断服务,在中断子程序中实现所有任务的DELAY计时自减,当为0时进入就绪态

点击(此处)折叠或打开

  1. OSTickISR
  2.   MOV R5,LR
  3.   MOV R1, #1
  4.   MOV R1, R1, LSL #10 ; Timer0 Source Pending Reg.
  5.   LDR R0, =SRCPND
  6.   LDR R2, [R0]
  7.   ORR R1, R1,R2
  8.   STR R1, [R0]
  9.   LDR R0, =INTPND
  10.   LDR R1, [R0]
  11.   STR R1, [R0]
  12. ;----------------------------------------------------------------------------------
  13. ; OSTimeTick();
  14. ;----------------------------------------------------------------------------------
  15.   BL OSTimeTick
  16.   MOV PC, R5 ; Return


将LR存入R5 SRCPND读取到R0 (SRCPND当一个中断发生后,那么相应的位会被置1,表示一个或一类中断发生了)

将寄存器值写入R2,R1=1<<10,R1 R2位或,赋值给R1,写入SRCPND//相当于给SRCPND|=(1<<10);

INTPND 优先级最高的中断裁决寄存器,只有最高优先级的中断才会被置位

读取INTPND的值到R1,跳转到OStimetick

将R5(原先LR的)的值赋给PC

阅读(2054) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~