os_cpu_a.asm
Upload User: jzqyzc
Upload Date: 2016-02-09
Package Size: 6475k
Code Size: 16k
Category:

SCM

Development Platform:

MultiPlatform

  1. ;********************************************************************************************************
  2. ;                                               uC/OS-II
  3. ;                                         The Real-Time Kernel
  4. ;
  5. ;                               (c) Copyright 1992-2004, Micrium, Weston, FL
  6. ;                                          All Rights Reserved
  7. ;
  8. ;                                           Generic ARM Port
  9. ;
  10. ; File      : OS_CPU_A.ASM
  11. ; Version   : V1.60
  12. ; By        : Jean J. Labrosse
  13. ;
  14. ; For       : ARM7 or ARM9
  15. ; Mode      : ARM or Thumb
  16. ; Toolchain : IAR's EWARM V4.11a and higher
  17. ;********************************************************************************************************
  18.             EXTERN  OSRunning                    ; External references
  19.             EXTERN  OSPrioCur
  20.             EXTERN  OSPrioHighRdy
  21.             EXTERN  OSTCBCur
  22.             EXTERN  OSTCBHighRdy
  23.             EXTERN  OSIntNesting
  24.             EXTERN  OSIntExit
  25.             EXTERN  OSTaskSwHook
  26.             EXTERN  OS_CPU_IRQ_ISR_Handler
  27.             EXTERN  OS_CPU_FIQ_ISR_Handler
  28.             PUBLIC  OS_CPU_SR_Save               ; Functions declared in this file
  29.             PUBLIC  OS_CPU_SR_Restore
  30.             PUBLIC  OSStartHighRdy               
  31.             PUBLIC  OSCtxSw
  32.             PUBLIC  OSIntCtxSw
  33.             PUBLIC  OS_CPU_IRQ_ISR
  34.             PUBLIC  OS_CPU_FIQ_ISR
  35. NO_INT      EQU     0xC0                         ; Mask used to disable interrupts (Both FIR and IRQ)
  36. SVC32_MODE  EQU     0x13
  37. FIQ32_MODE  EQU     0x11
  38. IRQ32_MODE  EQU     0x12
  39. ;*********************************************************************************************************
  40. ;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
  41. ;
  42. ; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
  43. ;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
  44. ;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to 
  45. ;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
  46. ;              into the CPU's status register.
  47. ;
  48. ; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
  49. ;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
  50. ;
  51. ;
  52. ; Note(s)    : 1) These functions are used in general like this:
  53. ;
  54. ;                 void Task (void *p_arg)
  55. ;                 {
  56. ;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
  57. ;                     OS_CPU_SR  cpu_sr;
  58. ;                 #endif
  59. ;
  60. ;                          :
  61. ;                          :
  62. ;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
  63. ;                          :
  64. ;                          :
  65. ;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
  66. ;                          :
  67. ;                          :
  68. ;                 }
  69. ;
  70. ;              2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note:
  71. ;
  72. ;                    "Disabling Interrupts at Processor Level"
  73. ;*********************************************************************************************************
  74.         RSEG CODE:CODE:NOROOT(2)
  75.         CODE32
  76. OS_CPU_SR_Save
  77.         MRS     R0,CPSR                     ; Set IRQ and FIQ bits in CPSR to disable all interrupts
  78.         ORR     R1,R0,#NO_INT
  79.         MSR     CPSR_c,R1
  80.         MRS     R1,CPSR                     ; Confirm that CPSR contains the proper interrupt disable flags
  81.         AND     R1,R1,#NO_INT
  82.         CMP     R1,#NO_INT
  83.         BNE     OS_CPU_SR_Save              ; Not properly disabled (try again)
  84.         BX      LR                          ; Disabled, return the original CPSR contents in R0
  85. OS_CPU_SR_Restore
  86.         MSR     CPSR_c,R0
  87.         BX      LR
  88. ;*********************************************************************************************************
  89. ;                                          START MULTITASKING
  90. ;                                       void OSStartHighRdy(void)
  91. ;
  92. ; Note(s) : 1) OSStartHighRdy() MUST:
  93. ;              a) Call OSTaskSwHook() then,
  94. ;              b) Set OSRunning to TRUE,
  95. ;              c) Switch to the highest priority task.
  96. ;*********************************************************************************************************
  97.         RSEG CODE:CODE:NOROOT(2)
  98.         CODE32
  99. OSStartHighRdy  
  100.         MSR     CPSR_cxsf, #0xD3        ; Switch to SVC mode with IRQ and FIQ disabled
  101.         LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
  102.         MOV     LR, PC
  103.         BX      R0            
  104.         LDR     R4, ??OS_Running        ; OSRunning = TRUE
  105.         MOV     R5, #1
  106.         STRB    R5, [R4]
  107.                                         ; SWITCH TO HIGHEST PRIORITY TASK
  108.         LDR     R4, ??OS_TCBHighRdy     ;    Get highest priority task TCB address
  109.         LDR     R4, [R4]                ;    get stack pointer
  110.         LDR     SP, [R4]                ;    switch to the new stack
  111.         LDR     R4,  [SP], #4           ;    pop new task's CPSR
  112.         MSR     SPSR_cxsf,R4
  113.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    pop new task's context
  114. ;*********************************************************************************************************
  115. ;                         PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
  116. ;
  117. ; Note(s) : 1) OSCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
  118. ;
  119. ;           2) The pseudo-code for OSCtxSw() is:
  120. ;              a) Save the current task's context onto the current task's stack
  121. ;              b) OSTCBCur->OSTCBStkPtr = SP;
  122. ;              c) OSTaskSwHook();
  123. ;              d) OSPrioCur             = OSPrioHighRdy;
  124. ;              e) OSTCBCur              = OSTCBHighRdy;
  125. ;              f) SP                    = OSTCBHighRdy->OSTCBStkPtr;
  126. ;              g) Restore the new task's context from the new task's stack
  127. ;              h) Return to new task's code
  128. ;
  129. ;           3) Upon entry: 
  130. ;              OSTCBCur      points to the OS_TCB of the task to suspend
  131. ;              OSTCBHighRdy  points to the OS_TCB of the task to resume
  132. ;*********************************************************************************************************
  133.         RSEG CODE:CODE:NOROOT(2)
  134.         CODE32
  135. OSCtxSw
  136.                                         ; SAVE CURRENT TASK'S CONTEXT
  137.         STMFD   SP!, {LR}               ;     Push return address
  138.         STMFD   SP!, {LR}
  139.         STMFD   SP!, {R0-R12}           ;     Push registers
  140.         MRS     R4,  CPSR               ;     Push current CPSR
  141.         TST     LR, #1                  ;     See if called from Thumb mode
  142.         ORRNE   R4,  R4, #0x20          ;     If yes, Set the T-bit
  143.         STMFD   SP!, {R4}
  144.         
  145.         LDR     R4, ??OS_TCBCur         ; OSTCBCur->OSTCBStkPtr = SP;
  146.         LDR     R5, [R4]
  147.         STR     SP, [R5]
  148.         LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
  149.         MOV     LR, PC
  150.         BX      R0            
  151.         LDR     R4, ??OS_PrioCur        ; OSPrioCur = OSPrioHighRdy
  152.         LDR     R5, ??OS_PrioHighRdy
  153.         LDRB    R6, [R5]
  154.         STRB    R6, [R4]
  155.         
  156.         LDR     R4, ??OS_TCBCur         ; OSTCBCur  = OSTCBHighRdy;
  157.         LDR     R6, ??OS_TCBHighRdy
  158.         LDR     R6, [R6]
  159.         STR     R6, [R4]
  160.         LDR     SP, [R6]                ; SP = OSTCBHighRdy->OSTCBStkPtr;
  161.                                         ; RESTORE NEW TASK'S CONTEXT
  162.         LDMFD   SP!, {R4}               ;    Pop new task's CPSR
  163.         MSR     SPSR_cxsf, R4
  164.         
  165.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    Pop new task's context
  166. ;*********************************************************************************************************
  167. ;                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
  168. ;
  169. ; Note(s) : 1) OSIntCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
  170. ;
  171. ;           2) The pseudo-code for OSCtxSw() is:
  172. ;              a) OSTaskSwHook();
  173. ;              b) OSPrioCur             = OSPrioHighRdy;
  174. ;              c) OSTCBCur              = OSTCBHighRdy;
  175. ;              d) SP                    = OSTCBHighRdy->OSTCBStkPtr;
  176. ;              e) Restore the new task's context from the new task's stack
  177. ;              f) Return to new task's code
  178. ;
  179. ;           3) Upon entry: 
  180. ;              OSTCBCur      points to the OS_TCB of the task to suspend
  181. ;              OSTCBHighRdy  points to the OS_TCB of the task to resume
  182. ;*********************************************************************************************************
  183.         RSEG CODE:CODE:NOROOT(2)
  184.         CODE32
  185. OSIntCtxSw
  186.         LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
  187.         MOV     LR, PC
  188.         BX      R0            
  189.         LDR     R4,??OS_PrioCur         ; OSPrioCur = OSPrioHighRdy
  190.         LDR     R5,??OS_PrioHighRdy
  191.         LDRB    R6,[R5]
  192.         STRB    R6,[R4]
  193.         
  194.         LDR     R4,??OS_TCBCur          ; OSTCBCur  = OSTCBHighRdy;
  195.         LDR     R6,??OS_TCBHighRdy
  196.         LDR     R6,[R6]
  197.         STR     R6,[R4]
  198.         LDR     SP,[R6]                 ; SP = OSTCBHighRdy->OSTCBStkPtr;
  199.                                         ; RESTORE NEW TASK'S CONTEXT
  200.         LDMFD   SP!, {R4}               ;    Pop new task's CPSR
  201.         MSR     SPSR_cxsf, R4
  202.         
  203.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    Pop new task's context
  204. ;*********************************************************************************************************
  205. ;                                      IRQ Interrupt Service Routine
  206. ;*********************************************************************************************************
  207.         RSEG CODE:CODE:NOROOT(2)
  208.         CODE32
  209. OS_CPU_IRQ_ISR
  210.         STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO IRQ STACK                     
  211.         
  212.         MOV     R1, SP                         ; Save   IRQ stack pointer
  213.         
  214.         ADD     SP, SP,#12                     ; Adjust IRQ stack pointer 
  215.         
  216.         SUB     R2, LR,#4                      ; Adjust PC for return address to task
  217.         MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
  218.         
  219.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  220.                                                ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
  221.         STMFD   SP!, {R2}                      ;    Push task's Return PC
  222.         STMFD   SP!, {LR}                      ;    Push task's LR
  223.         STMFD   SP!, {R4-R12}                  ;    Push task's R12-R4
  224.         
  225.         LDMFD   R1!, {R4-R6}                   ;    Move task's R1-R3 from IRQ stack to SVC stack
  226.         STMFD   SP!, {R4-R6}
  227.         STMFD   SP!, {R0}                      ;    Push task's R0    onto task's stack
  228.         STMFD   SP!, {R3}                      ;    Push task's CPSR (i.e. IRQ's SPSR)
  229.                 
  230.                                                ; HANDLE NESTING COUNTER
  231.         LDR     R0, ??OS_IntNesting            ; OSIntNesting++;
  232.         LDRB    R1, [R0]
  233.         ADD     R1, R1,#1
  234.         STRB    R1, [R0]
  235.         CMP     R1, #1                         ; if (OSIntNesting == 1) {
  236.         BNE     OS_CPU_IRQ_ISR_1
  237.         LDR     R4, ??OS_TCBCur                ;     OSTCBCur->OSTCBStkPtr = SP
  238.         LDR     R5, [R4]
  239.         STR     SP, [R5]                       ; }
  240. OS_CPU_IRQ_ISR_1
  241.         MSR     CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQ mode (to use the IRQ stack to handle interrupt)
  242.         
  243.         LDR     R0, ??OS_CPU_IRQ_ISR_Handler   ; OS_CPU_IRQ_ISR_Handler();
  244.         MOV     LR, PC
  245.         BX      R0            
  246.         
  247.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  248.         
  249.         LDR     R0, ??OS_IntExit               ; OSIntExit();
  250.         MOV     LR, PC
  251.         BX      R0            
  252.         
  253.                                                ; RESTORE NEW TASK'S CONTEXT
  254.         LDMFD   SP!, {R4}                      ;    Pop new task's CPSR
  255.         MSR     SPSR_cxsf, R4
  256.         
  257.         LDMFD   SP!, {R0-R12,LR,PC}^           ;    Pop new task's context
  258. ;*********************************************************************************************************
  259. ;                                      FIQ Interrupt Service Routine
  260. ;*********************************************************************************************************
  261.         RSEG CODE:CODE:NOROOT(2)
  262.         CODE32
  263. OS_CPU_FIQ_ISR
  264.                                         
  265.         STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO FIQ STACK                     
  266.         
  267.         MOV     R1, SP                         ; Save   FIQ stack pointer
  268.         
  269.         ADD     SP, SP,#12                     ; Adjust FIQ stack pointer 
  270.         
  271.         SUB     R2, LR,#4                      ; Adjust PC for return address to task
  272.         MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
  273.         
  274.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  275.                                                ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
  276.         STMFD   SP!, {R2}                      ;    Push task's Return PC
  277.         STMFD   SP!, {LR}                      ;    Push task's LR
  278.         STMFD   SP!, {R4-R12}                  ;    Push task's R12-R4
  279.         
  280.         LDMFD   R1!, {R4-R6}                   ;    Move task's R1-R3 from FIQ stack to SVC stack
  281.         STMFD   SP!, {R4-R6}
  282.         STMFD   SP!, {R0}                      ;    Push task's R0    onto task's stack
  283.         STMFD   SP!, {R3}                      ;    Push task's CPSR (i.e. FIQ's SPSR)
  284.                 
  285.                                                ; HANDLE NESTING COUNTER
  286.         LDR     R0, ??OS_IntNesting            ; OSIntNesting++;
  287.         LDRB    R1, [R0]
  288.         ADD     R1, R1,#1
  289.         STRB    R1, [R0]
  290.         CMP     R1, #1                         ; if (OSIntNesting == 1) {
  291.         BNE     OS_CPU_FIQ_ISR_1
  292.         LDR     R4, ??OS_TCBCur                ;     OSTCBCur->OSTCBStkPtr = SP
  293.         LDR     R5, [R4]
  294.         STR     SP, [R5]                       ; }
  295. OS_CPU_FIQ_ISR_1
  296.         MSR     CPSR_c, #(NO_INT | FIQ32_MODE) ; Change to FIQ mode (to use the FIQ stack to handle interrupt)
  297.         
  298.         LDR     R0, ??OS_CPU_FIQ_ISR_Handler   ; OS_CPU_FIQ_ISR_Handler();
  299.         MOV     LR, PC
  300.         BX      R0            
  301.         
  302.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  303.         
  304.         LDR     R0, ??OS_IntExit               ; OSIntExit();
  305.         MOV     LR, PC
  306.         BX      R0            
  307.         
  308.                                                ; RESTORE NEW TASK'S CONTEXT
  309.         LDMFD   SP!, {R4}                      ;    Pop new task's CPSR
  310.         MSR     SPSR_cxsf, R4
  311.         
  312.         LDMFD   SP!, {R0-R12,LR,PC}^           ;    Pop new task's context
  313. ;*********************************************************************************************************
  314. ;                                     POINTERS TO VARIABLES
  315. ;*********************************************************************************************************
  316.         DATA
  317.              
  318. ??OS_TaskSwHook:
  319.         DC32    OSTaskSwHook
  320. ??OS_CPU_IRQ_ISR_Handler:
  321.         DC32    OS_CPU_IRQ_ISR_Handler
  322. ??OS_CPU_FIQ_ISR_Handler:
  323.         DC32    OS_CPU_FIQ_ISR_Handler
  324. ??OS_IntExit:
  325.         DC32    OSIntExit
  326. ??OS_IntNesting:
  327.         DC32    OSIntNesting
  328. ??OS_PrioCur:
  329.         DC32    OSPrioCur
  330. ??OS_PrioHighRdy:
  331.         DC32    OSPrioHighRdy
  332. ??OS_Running:
  333.         DC32    OSRunning
  334. ??OS_TCBCur:
  335.         DC32    OSTCBCur
  336. ??OS_TCBHighRdy:
  337.         DC32    OSTCBHighRdy
  338.         END