OS_CPU_C.C
上传用户:jyxpgd88
上传日期:2013-04-13
资源大小:90k
文件大小:16k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                               uC/OS-II
  4. *                                         The Real-Time Kernel
  5. *
  6. *                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
  7. *                                          All Rights Reserved
  8. *
  9. *
  10. *                                       80x86/80x88 Specific code
  11. *                                          LARGE MEMORY MODEL
  12. *
  13. * File : OS_CPU_C.C
  14. * By   : Jean J. Labrosse
  15. *
  16. * Ported date:     Dec 2, 2003
  17. * By:              Stuart Wright (swright@jiskoot.com)
  18. * Target platform: Keil C51 V7.07 and above
  19. *         
  20. * Based on port for 8051 by John X. Liu, China, (johnxliu@163.com)
  21. ********************************************************************************************************
  22. */
  23. #define  OS_CPU_GLOBALS
  24. #include "ucos_ii.h"
  25. /*
  26. *********************************************************************************************************
  27. *                                        INITIALIZE A TASK'S STACK
  28. *
  29. * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
  30. *              stack frame of the task being created.  This function is highly processor specific.
  31. *
  32. * Arguments  : task          is a pointer to the task code
  33. *
  34. *              pdata  (vd)   is a pointer to a user supplied data area that will be passed to the task
  35. *                            when the task first executes. 
  36. *
  37. *              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
  38. *                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then 
  39. *                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
  40. *                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
  41. *                            of the stack.
  42. *
  43. *              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
  44. *                            (see uCOS_II.H for OS_TASK_OPT_???).
  45. *
  46. * Returns    : Always returns the location of the new top-of-stack' once the processor registers have
  47. *              been placed on the stack in the proper order.
  48. *
  49. * Note(s)    : Interrupts are enabled when your task starts executing. You can change this by setting the
  50. *              PSW to 0x0002 instead.  In this case, interrupts would be disabled upon task startup.  The
  51. *              application code would be responsible for enabling interrupts at the beginning of the task
  52. *              code.  You will need to modify OSTaskIdle() and OSTaskStat() so that they enable 
  53. *              interrupts.  Failure to do this will make your system crash!
  54. *********************************************************************************************************
  55. */
  56. /* The stack variable points to the start pointer in hardware stack and is defined in OS_CPU_A */
  57. extern idata unsigned char STACK_START[1];
  58. OS_STK *OSTaskStkInit (void (*task)(void *pd) KCREENTRANT, void * vd, OS_STK *ptos, INT16U opt) KCREENTRANT
  59. {
  60.     INT8U * stk;
  61.     opt    = opt;                           /* 'opt' is not used, prevent warning                      */
  62.     stk    = (INT8U *) ptos;                /* Load stack pointer                                      */
  63. stk -= sizeof(void *); /* Save the vd to external stack */
  64. *(void**)stk  = vd;                  /*                               */
  65. stk -= sizeof(INT16U);       /* The value should be loaded to PC    */
  66. *(INT16U*)stk  = (INT16U) task;        /* next time when this task is running */
  67. *--stk    = (INT8U )(((INT32U) task>>16)+0x7F);      /* Third byte of PC for dallas 390 */
  68. /* Following is the registers pushed into hardware stack */
  69. *--stk  = 'A';                 /* ACC */
  70. *--stk  = 'B';                 /* B   */
  71. *--stk  = 'X';                 /* DPX */
  72. *--stk  = 'H';                 /* DPH */
  73. *--stk  = 'L';                 /* DPL */
  74. // *--stk  = 'X';                 /* DPX1 for second DPTR */
  75. // *--stk  = 'H';                 /* DPH1 for second DPTR */
  76. // *--stk  = 'L';                 /* DPL1 for second DPTR */
  77. // *--stk  = DPS;                 /* DPS for second DPTR */
  78. *--stk  = PSW; /* PSW */
  79. *--stk  = 0;                   /* R0  */
  80. /*
  81. *--stk  = 1;                   // should be R1
  82. *--stk  = 2;                   // should be R2
  83. *--stk  = 3;                   // should be R3
  84. */
  85. stk -= sizeof(void *);      /* Keil C uses R1,R2,R3 to pass the */
  86. *(void**)stk  = vd;                  /* arguments of functions.          */
  87. *--stk  = 4;                   /* R4  */
  88. *--stk  = 5;                   /* R5  */
  89. *--stk  = 6;                   /* R6  */
  90. *--stk  = 7;                   /* R7  */
  91. /* Following is the registers pushed into hardware stack manually to support the dallas 390 */
  92.     *--stk           = 0x80;                /* IE, EA is enabled  */
  93. /*
  94.     Next is calculating the hardware stack pointer.
  95. */
  96.     *--stk  = (INT8U) STACK_START-1      /* Initial value when main was called    */
  97.                    +1                   /* IE */
  98.                    +8                   /* R0-R7, eight registers was saved      */
  99.                        +5                   /* ACC, B, DPH, DPL, PSW, five registers */
  100.                        +1                   /* Dallas 390 extra registers DPX1 */
  101. //                       +4                   /* Dallas 390 extra registers for second DPTR - DPL1 DPH1 DPX1 DPS */
  102.                        +sizeof(INT16U)      /* The PC value to be loaded             */
  103.                        +sizeof(INT8U)       /* The third byte of PC value to be loaded for dallas 390  */
  104.    ;
  105.     return ((void *)stk);
  106. }
  107. OS_EXT  OS_TCB      *OSTCBHighRdy;                    /* Pointer to highest priority TCB ready to run  */
  108. void LoadCtx() KCREENTRANT;   /* Save the current working registers to stack, defined in OS_CPU_A.ASM */
  109. extern INT8U xdata * data C_XBP;
  110. /*
  111. ***********************************************************************************************************
  112. * OSStartHighRdy: START MULTITASKING
  113. *     
  114. * Duty:     a) Call OSTaskSwHook() then,
  115. *           b) Set OSRunning to TRUE,
  116. *           c) Switch to the highest priority task.
  117. *
  118. ***********************************************************************************************************
  119. */
  120. void OSStartHighRdy(void) KCREENTRANT
  121. {
  122.     OSTaskSwHook();
  123. OSRunning=1;
  124. C_XBP=OSTCBHighRdy->OSTCBStkPtr;
  125. LoadCtx();
  126. }
  127. /**********************************************************************************************************
  128. * C_OSCtxSw is the c part of OSCtxSw.
  129. * When control passes to this function, the processor registers have been saved in external stack
  130. ***********************************************************************************************************/
  131. void C_OSCtxSw(void) KCREENTRANT
  132. {
  133. /* Save processor registers; DONE in the OSCtxSw part in OS_CPU_ASM.ASM                                  */
  134. /* Save the current task's stack pointer into the current task's OS_TCB:  
  135. OSTCBCur->OSTCBStkPtr = Stack pointer;
  136. Call user definable OSTaskSwHook();                                    
  137. OSTCBCur  = OSTCBHighRdy;                                              
  138. OSPrioCur = OSPrioHighRdy;                                             
  139. Get the stack pointer of the task to resume:                           
  140. Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
  141. Restore all processor registers from the new task's stack;             
  142. Execute a return from interrupt instruction;                           */
  143.     OSTCBCur->OSTCBStkPtr = C_XBP;
  144.     
  145. OSTaskSwHook();
  146.     OSTCBCur  = OSTCBHighRdy;
  147.     OSPrioCur = OSPrioHighRdy;
  148.     C_XBP       = OSTCBCur->OSTCBStkPtr;
  149.     LoadCtx();
  150. }
  151. INT8U data SaveSP;
  152. void OSIntCtxSw(void) KCREENTRANT
  153. {
  154. EA=0;
  155.     SP=SaveSP;
  156.     C_XBP=OSTCBCur->OSTCBStkPtr;
  157. #pragma ASM
  158. EXTRN   CODE(_?KCOSCtxSw)
  159. MOV A, #BYTE0( _?KCOSCtxSw)
  160. PUSH ACC
  161. MOV A, #BYTE1(_?KCOSCtxSw)
  162. PUSH ACC
  163. MOV A, #BYTE2(_?KCOSCtxSw)
  164. PUSH ACC
  165. RETI
  166. #pragma ENDASM
  167. }
  168. /* OSTickISR can be writen in c language now, so it is more easy for user to write code for their own */
  169. void OSTickISR(void) interrupt 1
  170. {
  171. /* Do this first */
  172.     OSIntNesting++;                      /* Increment ISR nesting level directly to speed up processing */
  173. // OSIntEnter(); /* Must be called first at every hardware interrupt entry point */
  174.     if(OSIntNesting==1)                     /* Only at the outerest interrupt we do these. */
  175. {
  176. #pragma ASM
  177. PUSH IE
  178. #pragma ENDASM
  179. EA=0;
  180. SaveSP=SP;
  181.         OSTCBCur->OSTCBStkPtr=C_XBP; /* OSTCBCur->OSTCBStkPtr is free now, so it can be used to story the value of SP */
  182. EA=1;
  183.      }
  184.     OSTimeTick(); /* Must be called during tick isr */
  185.     OSIntExit(); /* Must be called finally at every hardware interupt exit point */
  186.     if(OSIntNesting==0)
  187. {
  188. EA=0;
  189.         C_XBP=OSTCBCur->OSTCBStkPtr;
  190. SP=SaveSP;
  191. #pragma ASM
  192. POP  IE
  193. #pragma ENDASM
  194. }
  195. }
  196. /* Sample user ISR: Serial communication */
  197. /* If you want to write ISRs for your own, just do as following */
  198. void SerialIntr(void) interrupt 4
  199. {
  200. /* Do this first */
  201.     OSIntNesting++;                      /* Increment ISR nesting level directly to speed up processing */
  202. // OSIntEnter(); /* Must be called first at every hardware interrupt entry point */
  203.     if(OSIntNesting==1)                     /* Only at the outerest interrupt we do these. */
  204. {
  205. #pragma ASM
  206. PUSH IE
  207. #pragma ENDASM
  208. EA=0;
  209. SaveSP=SP;
  210.         OSTCBCur->OSTCBStkPtr=C_XBP; /* OSTCBCur->OSTCBStkPtr is free now, so it can be used to story the value of SP */
  211. EA=1;
  212.      }
  213. /* Next you can do something for yourself. */
  214. /* Finally, before exit from ISR, must do as following. */
  215.     OSIntExit(); /* Must be called finally at every hardware interupt exit point */
  216.     if(OSIntNesting==0)
  217. {
  218. EA=0;
  219.         C_XBP=OSTCBCur->OSTCBStkPtr;
  220. SP=SaveSP;
  221. #pragma ASM
  222. POP  IE
  223. #pragma ENDASM
  224. }
  225. }
  226. /*$PAGE*/
  227. #if OS_CPU_HOOKS_EN
  228. /*
  229. *********************************************************************************************************
  230. *                                       OS INITIALIZATION HOOK
  231. *                                            (BEGINNING)
  232. *
  233. * Description: This function is called by OSInit() at the beginning of OSInit().
  234. *
  235. * Arguments  : none
  236. *
  237. * Note(s)    : 1) Interrupts should be disabled during this call.
  238. *********************************************************************************************************
  239. */
  240. #if OS_VERSION > 203
  241. void OSInitHookBegin (void) KCREENTRANT
  242. {
  243. }
  244. #endif
  245. /*
  246. *********************************************************************************************************
  247. *                                       OS INITIALIZATION HOOK
  248. *                                               (END)
  249. *
  250. * Description: This function is called by OSInit() at the end of OSInit().
  251. *
  252. * Arguments  : none
  253. *
  254. * Note(s)    : 1) Interrupts should be disabled during this call.
  255. *********************************************************************************************************
  256. */
  257. #if OS_VERSION > 203
  258. void OSInitHookEnd (void) KCREENTRANT
  259. {
  260. }
  261. #endif
  262. /*
  263. *********************************************************************************************************
  264. *                                          TASK CREATION HOOK
  265. *
  266. * Description: This function is called when a task is created.
  267. *
  268. * Arguments  : ptcb   is a pointer to the task control block of the task being created.
  269. *
  270. * Note(s)    : 1) Interrupts are disabled during this call.
  271. *********************************************************************************************************
  272. */
  273. void OSTaskCreateHook (OS_TCB *ptcb) KCREENTRANT
  274. {
  275.     ptcb = ptcb;                       /* Prevent compiler warning                                     */
  276. }
  277. /*
  278. *********************************************************************************************************
  279. *                                           TASK DELETION HOOK
  280. *
  281. * Description: This function is called when a task is deleted.
  282. *
  283. * Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
  284. *
  285. * Note(s)    : 1) Interrupts are disabled during this call.
  286. *********************************************************************************************************
  287. */
  288. #if OS_TASK_DEL_EN > 0
  289. void OSTaskDelHook (OS_TCB *ptcb) KCREENTRANT
  290. {
  291.     ptcb = ptcb;                       /* Prevent compiler warning                                     */
  292. }
  293. #endif
  294. /*
  295. *********************************************************************************************************
  296. *                                           TASK SWITCH HOOK
  297. *
  298. * Description: This function is called when a task switch is performed.  This allows you to perform other
  299. *              operations during a context switch.
  300. *
  301. * Arguments  : none
  302. *
  303. * Note(s)    : 1) Interrupts are disabled during this call.
  304. *              2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
  305. *                 will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the 
  306. *                 task being switched out (i.e. the preempted task).
  307. *********************************************************************************************************
  308. */
  309. void OSTaskSwHook (void) KCREENTRANT
  310. {
  311. }
  312. /*
  313. *********************************************************************************************************
  314. *                                           STATISTIC TASK HOOK
  315. *
  316. * Description: This function is called every second by uC/OS-II's statistics task.  This allows your 
  317. *              application to add functionality to the statistics task.
  318. *
  319. * Arguments  : none
  320. *********************************************************************************************************
  321. */
  322. void OSTaskStatHook (void) KCREENTRANT
  323. {
  324. }
  325. /*
  326. *********************************************************************************************************
  327. *                                           OSTCBInit() HOOK
  328. *
  329. * Description: This function is called by OSTCBInit() after setting up most of the TCB.
  330. *
  331. * Arguments  : ptcb    is a pointer to the TCB of the task being created.
  332. *
  333. * Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
  334. *********************************************************************************************************
  335. */
  336. #if OS_VERSION > 203
  337. void OSTCBInitHook (OS_TCB *ptcb) KCREENTRANT
  338. {
  339.     ptcb = ptcb;                                           /* Prevent Compiler warning                 */
  340. }
  341. #endif
  342. /*
  343. *********************************************************************************************************
  344. *                                               TICK HOOK
  345. *
  346. * Description: This function is called every tick.
  347. *
  348. * Arguments  : none
  349. *
  350. * Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
  351. *********************************************************************************************************
  352. */
  353. void OSTimeTickHook (void) KCREENTRANT
  354. {
  355. }
  356. /*
  357. *********************************************************************************************************
  358. *                                             IDLE TASK HOOK
  359. *
  360. * Description: This function is called by the idle task.  This hook has been added to allow you to do  
  361. *              such things as STOP the CPU to conserve power.
  362. *
  363. * Arguments  : none
  364. *
  365. * Note(s)    : 1) Interrupts are enabled during this call.
  366. *********************************************************************************************************
  367. */
  368. #if OS_VERSION >= 251
  369. void OSTaskIdleHook (void) KCREENTRANT
  370. {
  371. }
  372. #endif
  373. #endif