os_cpu_a.asm
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:12k
源码类别:

uCOS

开发平台:

C/C++

  1. ;********************************************************************************************************
  2. ;                                               uC/OS-II
  3. ;                                         The Real-Time Kernel
  4. ;
  5. ;                               (c) Copyright 1992-2006, Micrium, Weston, FL
  6. ;                                          All Rights Reserved
  7. ;
  8. ;                                           Generic ARM Port
  9. ;
  10. ; File      : OS_CPU_A.ASM
  11. ; Version   : V2.86(fix)
  12. ; By        : Jean J. Labrosse
  13. ;
  14. ; For       : ARMv7M Cortex-M3
  15. ; Mode      : Thumb2
  16. ; Toolchain : RealView Development Suite
  17. ;             RealView Microcontroller Development Kit (MDK)
  18. ;             ARM Developer Suite (ADS)
  19. ;             Keil uVision
  20. ;********************************************************************************************************
  21. ;********************************************************************************************************
  22. ;                                           PUBLIC FUNCTIONS
  23. ;********************************************************************************************************
  24.     EXTERN  OSRunning                                           ; External references
  25.     EXTERN  OSPrioCur
  26.     EXTERN  OSPrioHighRdy
  27.     EXTERN  OSTCBCur
  28.     EXTERN  OSTCBHighRdy
  29.     EXTERN  OSIntNesting
  30.     EXTERN  OSIntExit
  31.     EXTERN  OSTaskSwHook
  32.     EXPORT  OS_CPU_SR_Save                                      ; Functions declared in this file
  33.     EXPORT  OS_CPU_SR_Restore
  34.     EXPORT  OSStartHighRdy
  35.     EXPORT  OSCtxSw
  36.     EXPORT  OSIntCtxSw
  37.     EXPORT  OS_CPU_PendSVHandler
  38. ;********************************************************************************************************
  39. ;                                                EQUATES
  40. ;********************************************************************************************************
  41. NVIC_INT_CTRL   EQU     0xE000ED04                              ; Interrupt control state register.
  42. NVIC_SYSPRI2    EQU     0xE000ED20                              ; System priority register (priority 2).
  43. NVIC_PENDSV_PRI EQU     0xFFFF                              ; PendSV priority value (lowest).
  44. NVIC_PENDSVSET  EQU     0x10000000                              ; Value to trigger PendSV exception.
  45. ;********************************************************************************************************
  46. ;                                      CODE GENERATION DIRECTIVES
  47. ;********************************************************************************************************
  48.     AREA |.text|, CODE, READONLY, ALIGN=2
  49.     THUMB
  50.     REQUIRE8
  51.     PRESERVE8
  52. ;********************************************************************************************************
  53. ;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
  54. ;
  55. ; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
  56. ;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
  57. ;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
  58. ;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
  59. ;              into the CPU's status register.
  60. ;
  61. ; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
  62. ;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
  63. ;
  64. ;
  65. ; Note(s)    : 1) These functions are used in general like this:
  66. ;
  67. ;                 void Task (void *p_arg)
  68. ;                 {
  69. ;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
  70. ;                     OS_CPU_SR  cpu_sr;
  71. ;                 #endif
  72. ;
  73. ;                          :
  74. ;                          :
  75. ;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
  76. ;                          :
  77. ;                          :
  78. ;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
  79. ;                          :
  80. ;                          :
  81. ;                 }
  82. ;********************************************************************************************************
  83. OS_CPU_SR_Save
  84.     MRS     R0, PRIMASK                                         ; Set prio int mask to mask all (except faults)
  85.     CPSID   I
  86.     BX      LR
  87. OS_CPU_SR_Restore
  88.     MSR     PRIMASK, R0
  89.     BX      LR
  90. ;********************************************************************************************************
  91. ;                                          START MULTITASKING
  92. ;                                       void OSStartHighRdy(void)
  93. ;
  94. ; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
  95. ;              the first task to start.
  96. ;
  97. ;           2) OSStartHighRdy() MUST:
  98. ;              a) Setup PendSV exception priority to lowest;
  99. ;              b) Set initial PSP to 0, to tell context switcher this is first run;
  100. ;              c) Set OSRunning to TRUE;
  101. ;              d) Trigger PendSV exception;
  102. ;              e) Enable interrupts (tasks will run with interrupts enabled).
  103. ;********************************************************************************************************
  104. OSStartHighRdy
  105.     LDR     R0, =NVIC_SYSPRI2                                   ; Set the PendSV exception priority
  106.     LDR     R1, =NVIC_PENDSV_PRI
  107.     STRB    R1, [R0]
  108.     MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call
  109.     MSR     PSP, R0
  110.     LDR     R0, =OSRunning                                      ; OSRunning = TRUE
  111.     MOVS    R1, #1
  112.     STRB    R1, [R0]
  113.     LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
  114.     LDR     R1, =NVIC_PENDSVSET
  115.     STR     R1, [R0]
  116.     CPSIE   I                                                   ; Enable interrupts at processor level
  117. OSStartHang
  118.     B       OSStartHang                                         ; Should never get here
  119. ;********************************************************************************************************
  120. ;                               PERFORM A CONTEXT SWITCH (From task level)
  121. ;                                           void OSCtxSw(void)
  122. ;
  123. ; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
  124. ;              triggers the PendSV exception which is where the real work is done.
  125. ;********************************************************************************************************
  126. OSCtxSw
  127.     LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
  128.     LDR     R1, =NVIC_PENDSVSET
  129.     STR     R1, [R0]
  130.     BX      LR
  131. ;********************************************************************************************************
  132. ;                             PERFORM A CONTEXT SWITCH (From interrupt level)
  133. ;                                         void OSIntCtxSw(void)
  134. ;
  135. ; Notes:    1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
  136. ;              the result of an interrupt.  This function simply triggers a PendSV exception which will
  137. ;              be handled when there are no more interrupts active and interrupts are enabled.
  138. ;********************************************************************************************************
  139. OSIntCtxSw
  140.     LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
  141.     LDR     R1, =NVIC_PENDSVSET
  142.     STR     R1, [R0]
  143.     BX      LR
  144. ;********************************************************************************************************
  145. ;                                         HANDLE PendSV EXCEPTION
  146. ;                                     void OS_CPU_PendSVHandler(void)
  147. ;
  148. ; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
  149. ;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
  150. ;              processor context on any exception, and restores same on return from exception.  So only
  151. ;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
  152. ;              this way means that context saving and restoring is identical whether it is initiated from
  153. ;              a thread or occurs due to an interrupt or exception.
  154. ;
  155. ;           2) Pseudo-code is:
  156. ;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
  157. ;              b) Save remaining regs r4-r11 on process stack;
  158. ;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
  159. ;              d) Call OSTaskSwHook();
  160. ;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
  161. ;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
  162. ;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
  163. ;              h) Restore R4-R11 from new process stack;
  164. ;              i) Perform exception return which will restore remaining context.
  165. ;
  166. ;           3) On entry into PendSV handler:
  167. ;              a) The following have been saved on the process stack (by processor):
  168. ;                 xPSR, PC, LR, R12, R0-R3
  169. ;              b) Processor mode is switched to Handler mode (from Thread mode)
  170. ;              c) Stack is Main stack (switched from Process stack)
  171. ;              d) OSTCBCur      points to the OS_TCB of the task to suspend
  172. ;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
  173. ;
  174. ;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
  175. ;              know that it will only be run when no other exception or interrupt is active, and
  176. ;              therefore safe to assume that context being switched out was using the process stack (PSP).
  177. ;********************************************************************************************************
  178. OS_CPU_PendSVHandler
  179.     CPSID   I                                                   ; Prevent interruption during context switch
  180.     MRS     R0, PSP                                             ; PSP is process stack pointer
  181.     CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time
  182.     SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
  183.     STM     R0, {R4-R11}
  184.     LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
  185.     LDR     R1, [R1]
  186.     STR     R0, [R1]                                            ; R0 is SP of process being switched out
  187.                                                                 ; At this point, entire context of process has been saved
  188. OS_CPU_PendSVHandler_nosave
  189.     PUSH    {R14}                                               ; Save LR exc_return value
  190.     LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
  191.     BLX     R0
  192.     POP     {R14}
  193.     LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
  194.     LDR     R1, =OSPrioHighRdy
  195.     LDRB    R2, [R1]
  196.     STRB    R2, [R0]
  197.     LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
  198.     LDR     R1, =OSTCBHighRdy
  199.     LDR     R2, [R1]
  200.     STR     R2, [R0]
  201.     LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
  202.     LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
  203.     ADDS    R0, R0, #0x20
  204.     MSR     PSP, R0                                             ; Load PSP with new process SP
  205.     ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
  206.     CPSIE   I
  207.     BX      LR                                                  ; Exception return will restore remaining context
  208.     END