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

全部博文(103)

文章存档

2013年(4)

2012年(99)

我的朋友

分类: LINUX

2012-11-14 11:47:49

 
操作系统的调度方法是其核心,下面是μc的调度函数

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * SCHEDULER
  4. *
  5. * Description: This function is called by other uC/OS-II services to determine whether a new, high
  6. * priority task has been made ready to run. This function is invoked by TASK level code
  7. * and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
  8. *
  9. * Arguments : none
  10. *
  11. * Returns : none
  12. *
  13. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  14. * 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
  15. *********************************************************************************************************
  16. */

  17. void OS_Sched (void)
  18. {
  19. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
  20.     OS_CPU_SR cpu_sr = 0;
  21. #endif



  22.     OS_ENTER_CRITICAL();
  23.     if (OSIntNesting == 0) { /* Schedule only if all ISRs done and ... */
  24.         if (OSLockNesting == 0) { /* ... scheduler is not locked */
  25.             OS_SchedNew();
  26.             if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
  27.                 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
  28. #if OS_TASK_PROFILE_EN > 0
  29.                 OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
  30. #endif
  31.                 OSCtxSwCtr++; /* Increment context switch counter */
  32.                 OS_TASK_SW(); /* Perform a context switch */
  33.             }
  34.         }
  35.     }
  36.     OS_EXIT_CRITICAL();
  37. }

首先,关中断,判断是否在IRQ中(是否嵌套大于0),如果不在,可以执行调度
然后,判断调度是否被禁止OSLockNesting == 0
调用OS_SchedNew();函数调度

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * FIND HIGHEST PRIORITY TASK READY TO RUN
  4. *
  5. * Description: This function is called by other uC/OS-II services to determine the highest priority task
  6. * that is ready to run. The global variable 'OSPrioHighRdy' is changed accordingly.
  7. *
  8. * Arguments : none
  9. *
  10. * Returns : none
  11. *
  12. * Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
  13. * 2) Interrupts are assumed to be disabled when this function is called.
  14. *********************************************************************************************************
  15. */

  16. static void OS_SchedNew (void)
  17. {
  18. #if OS_LOWEST_PRIO <= 63 /* See if we support up to 64 tasks */
  19.     INT8U y;


  20.     y = OSUnMapTbl[OSRdyGrp];
  21.     OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
  22. #else /* We support up to 256 tasks */
  23.     INT8U y;
  24.     INT16U *ptbl;


  25.     if ((OSRdyGrp & 0xFF) != 0) {
  26.         y = OSUnMapTbl[OSRdyGrp & 0xFF];
  27.     } else {
  28.         y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8;
  29.     }
  30.     ptbl = &OSRdyTbl[y];
  31.     if ((*ptbl & 0xFF) != 0) {
  32.         OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]);
  33.     } else {
  34.         OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8);
  35.     }
  36. #endif
  37. }
当最低优先级小于63时,即优先级只有0-63,那么执行就绪表最高优先级查找算法OSUnMapTbl[]
当优先级大于63时,4位表示一个表元素,
最后都将最高优先级写入OSPrioHighRdy变量
 
检查OSPrioHighRdy和现在运行的任务的优先级是不是匹配,如果不是当前运行的程序
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy],修改要运行的最高优先级TCB
如果使能Ext,OSTCBHighRdy->OSTCBCtxSwCtr++;将切换次数变量自加
OSCtxSwCtr++;系统上下文切换计数器自加
OS_TASK_SW();切换任务

点击(此处)折叠或打开

  1. ;**********************************************************************************************************
  2. ; PERFORM A CONTEXT SWITCH (From task level)
  3. ; void OSCtxSw(void)
  4. ;
  5. ; Note(s): 1) Upon entry:
  6. ; OSTCBCur points to the OS_TCB of the task to suspend
  7. ; OSTCBHighRdy points to the OS_TCB of the task to resume
  8. ;
  9. ; 2) The stack frame of the task to suspend looks as follows:
  10. ;
  11. ; PC (High memory)
  12. ; LR(R14)
  13. ; R12
  14. ; R11
  15. ; R10
  16. ; R9
  17. ; R8
  18. ; R7
  19. ; R6
  20. ; R5
  21. ; R4
  22. ; R3
  23. ; R2
  24. ; R1
  25. ; R0
  26. ; OSTCBCur->OSTCBStkPtr ----> CPSR (Low memory)
  27. ;
  28. ;
  29. ; 3) The stack frame of the task to resume looks as follows:
  30. ;
  31. ; PC (High memory)
  32. ; LR(R14)
  33. ; R12
  34. ; R11
  35. ; R10
  36. ; R9
  37. ; R8
  38. ; R7
  39. ; R6
  40. ; R5
  41. ; R4
  42. ; R3
  43. ; R2
  44. ; R1
  45. ; R0
  46. ; OSTCBHighRdy->OSTCBStkPtr ----> CPSR (Low memory)
  47. ;*********************************************************************************************************/
  48. OSCtxSw
  49. STMFD SP!, {LR} ;PC
  50. STMFD SP!, {R0-R12, LR} ;R0-R12 LR
  51. MRS R0, CPSR ;Push CPSR
  52. STMFD SP!, {R0}
  53. ;----------------------------------------------------------------------------------
  54. ; OSTCBCur->OSTCBStkPtr = SP
  55. ;----------------------------------------------------------------------------------
  56. LDR R0, =OSTCBCur
  57. LDR R0, [R0]
  58. STR SP, [R0]
  59. ;----------------------------------------------------------------------------------
  60. ; OSTaskSwHook();
  61. ;---------------------------------------------------------------------------------
  62. BL OSTaskSwHook
  63. ;----------------------------------------------------------------------------------
  64. ; OSTCBCur = OSTCBHighRdy;
  65. ;----------------------------------------------------------------------------------
  66. LDR R0, =OSTCBHighRdy
  67. LDR R1, =OSTCBCur
  68. LDR R0, [R0]
  69. STR R0, [R1]
  70. ;----------------------------------------------------------------------------------
  71. ; OSPrioCur = OSPrioHighRdy;
  72. ;----------------------------------------------------------------------------------
  73. LDR R0, =OSPrioHighRdy
  74. LDR R1, =OSPrioCur
  75. LDRB R0, [R0]
  76. STRB R0, [R1]
  77. ;----------------------------------------------------------------------------------
  78. ; OSTCBHighRdy->OSTCBStkPtr;
  79. ;----------------------------------------------------------------------------------
  80. LDR R0, =OSTCBHighRdy
  81. LDR R0, [R0]
  82. LDR SP, [R0]
  83. ;----------------------------------------------------------------------------------
  84. ;Restore New task context
  85. ;----------------------------------------------------------------------------------
  86. LDMFD SP!, {R0} ;POP CPSR
  87. MSR SPSR_cxsf, R0
  88. LDMFD SP!, {R0-R12, LR, PC}^
完成三个任务,
第一,OSTCBCur修改指向将要被挂起任务的TCB,将OSTCBHighRdy指向将要被运行的任务的TCB
。。。 
以前看过的ARM体系结构和指令集都忘记了,必经没有实际使用过,没有深刻的印象,今天对照着指令集从新看过这个汇编函数:
这个函数做了三件事情
第一步,把当前任务对应的R0-R12压栈,使用STMFD指令将PC写入LR(R14)寄存器,使用回写‘!’指令使其写入的地址递增,将寄存器值压入栈的顺序为FD满栈递减,从栈底开始向低地址写入寄存器值
第二步,OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy; SP=OSTCBHighRdy->OSTCBStkPtr;
具体实现了最高优先级prio和TCB对现在运行的prio和TCB的同步
将SP(R13)指向现在要运行的TCB的栈指针
第三步,对切换后的任务TCB的栈进行弹栈操作,使用LDMFD弹出CPSR到R0 使用MSR将R0写入SPSR,弹出R0-R12 R14 R15
 
 
 
阅读(1382) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~