os_cpu_a.s
上传用户:yyyd609
上传日期:2022-07-18
资源大小:183k
文件大小:16k
源码类别:

微处理器开发

开发平台:

C/C++

  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 : ARM Developer Suite Version 1.2 and higher
  17. ;********************************************************************************************************
  18.             IMPORT  OSRunning                    ; External references
  19.             IMPORT  OSPrioCur
  20.             IMPORT  OSPrioHighRdy
  21.             IMPORT  OSTCBCur
  22.             IMPORT  OSTCBHighRdy
  23.             IMPORT  OSIntNesting
  24.             IMPORT  OSIntExit
  25.             IMPORT  OSTaskSwHook
  26.             IMPORT  OSTimeTick
  27.             IMPORT  FIQ_Handler
  28.             EXPORT  OS_CPU_SR_Save               ; Functions declared in this file
  29.             EXPORT  OS_CPU_SR_Restore
  30.             EXPORT  OSStartHighRdy               
  31.             EXPORT  OSCtxSw
  32.             EXPORT  OSIntCtxSw
  33.             EXPORT  OS_CPU_IRQ_ISR
  34.             EXPORT  OS_CPU_FIQ_ISR
  35. NO_INT      EQU     0xC0                         ; Mask used to disable interrupts (Both FIR and IRQ)
  36. FIQ32_MODE  EQU     0x11
  37. IRQ32_MODE  EQU     0x12
  38. SVC32_MODE  EQU     0x13
  39.             AREA    |.text|,CODE
  40.             CODE32
  41. ;*********************************************************************************************************
  42. ;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
  43. ;
  44. ; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
  45. ;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
  46. ;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to 
  47. ;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
  48. ;              into the CPU's status register.
  49. ;
  50. ; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
  51. ;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
  52. ;
  53. ;
  54. ; Note(s)    : 1) These functions are used in general like this:
  55. ;
  56. ;                 void Task (void *p_arg)
  57. ;                 {
  58. ;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
  59. ;                     OS_CPU_SR  cpu_sr;
  60. ;                 #endif
  61. ;
  62. ;                          :
  63. ;                          :
  64. ;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
  65. ;                          :
  66. ;                          :
  67. ;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
  68. ;                          :
  69. ;                          :
  70. ;                 }
  71. ;
  72. ;              2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note:
  73. ;
  74. ;                    "Disabling Interrupts at Processor Level"
  75. ;*********************************************************************************************************
  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. OSStartHighRdy
  98.         MSR     CPSR_c, #(NO_INT | SVC32_MODE)
  99.                                         ; Switch to SVC mode with IRQ and FIQ disabled
  100.         LDR     R0, =OSTaskSwHook       ; OSTaskSwHook();
  101.         MOV     LR, PC
  102.         BX      R0            
  103.         LDR     R4, =OSRunning          ; OSRunning = TRUE
  104.         MOV     R5, #1
  105.         STRB    R5, [R4]
  106.                                         ; SWITCH TO HIGHEST PRIORITY TASK
  107.         LDR     R4, =OSTCBHighRdy       ;    Get highest priority task TCB address
  108.         LDR     R4, [R4]                ;    get stack pointer
  109.         LDR     SP, [R4]                ;    switch to the new stack
  110.         LDR     R4,  [SP], #4           ;    pop new task's CPSR
  111.         MSR     SPSR_cxsf,R4
  112.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    pop new task's context
  113. ;*********************************************************************************************************
  114. ;                         PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
  115. ;
  116. ; Note(s) : 1) OSCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
  117. ;
  118. ;           2) The pseudo-code for OSCtxSw() is:
  119. ;              a) Save the current task's context onto the current task's stack
  120. ;              b) OSTCBCur->OSTCBStkPtr = SP;
  121. ;              c) OSTaskSwHook();
  122. ;              d) OSPrioCur             = OSPrioHighRdy;
  123. ;              e) OSTCBCur              = OSTCBHighRdy;
  124. ;              f) SP                    = OSTCBHighRdy->OSTCBStkPtr;
  125. ;              g) Restore the new task's context from the new task's stack
  126. ;              h) Return to new task's code
  127. ;
  128. ;           3) Upon entry: 
  129. ;              OSTCBCur      points to the OS_TCB of the task to suspend
  130. ;              OSTCBHighRdy  points to the OS_TCB of the task to resume
  131. ;*********************************************************************************************************
  132. OSCtxSw
  133.                                         ; SAVE CURRENT TASK'S CONTEXT
  134.         STMFD   SP!, {LR}               ;     Push return address
  135.         STMFD   SP!, {LR}
  136.         STMFD   SP!, {R0-R12}           ;     Push registers
  137.         MRS     R4,  CPSR               ;     Push current CPSR
  138.         TST     LR, #1                  ;     See if called from Thumb mode
  139.         ORRNE   R4,  R4, #0x20          ;     If yes, Set the T-bit
  140.         STMFD   SP!, {R4}
  141.         
  142.         LDR     R4, =OSTCBCur           ; OSTCBCur->OSTCBStkPtr = SP;
  143.         LDR     R5, [R4]
  144.         STR     SP, [R5]
  145.         LDR     R0, =OSTaskSwHook       ; OSTaskSwHook();
  146.         MOV     LR, PC
  147.         BX      R0            
  148.         LDR     R4, =OSPrioCur          ; OSPrioCur = OSPrioHighRdy
  149.         LDR     R5, =OSPrioHighRdy
  150.         LDRB    R6, [R5]
  151.         STRB    R6, [R4]
  152.         
  153.         LDR     R4, =OSTCBCur           ; OSTCBCur  = OSTCBHighRdy;
  154.         LDR     R6, =OSTCBHighRdy
  155.         LDR     R6, [R6]
  156.         STR     R6, [R4]
  157.         LDR     SP, [R6]                ; SP = OSTCBHighRdy->OSTCBStkPtr;
  158.                                         ; RESTORE NEW TASK'S CONTEXT
  159.         LDMFD   SP!, {R4}               ;    Pop new task's CPSR
  160.         MSR     SPSR_cxsf, R4
  161.         
  162.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    Pop new task's context
  163. ;*********************************************************************************************************
  164. ;                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
  165. ;
  166. ; Note(s) : 1) OSIntCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
  167. ;
  168. ;           2) The pseudo-code for OSCtxSw() is:
  169. ;              a) OSTaskSwHook();
  170. ;              b) OSPrioCur             = OSPrioHighRdy;
  171. ;              c) OSTCBCur              = OSTCBHighRdy;
  172. ;              d) SP                    = OSTCBHighRdy->OSTCBStkPtr;
  173. ;              e) Restore the new task's context from the new task's stack
  174. ;              f) Return to new task's code
  175. ;
  176. ;           3) Upon entry: 
  177. ;              OSTCBCur      points to the OS_TCB of the task to suspend
  178. ;              OSTCBHighRdy  points to the OS_TCB of the task to resume
  179. ;*********************************************************************************************************
  180. OSIntCtxSw
  181.         LDR     R0, =OSTaskSwHook       ; OSTaskSwHook();
  182.         MOV     LR, PC
  183.         BX      R0            
  184.         LDR     R4,=OSPrioCur           ; OSPrioCur = OSPrioHighRdy
  185.         LDR     R5,=OSPrioHighRdy
  186.         LDRB    R6,[R5]
  187.         STRB    R6,[R4]
  188.         
  189.         LDR     R4,=OSTCBCur            ; OSTCBCur  = OSTCBHighRdy;
  190.         LDR     R6,=OSTCBHighRdy
  191.         LDR     R6,[R6]
  192.         STR     R6,[R4]
  193.         LDR     SP,[R6]                 ; SP = OSTCBHighRdy->OSTCBStkPtr;
  194.                                         ; RESTORE NEW TASK'S CONTEXT
  195.         LDMFD   SP!, {R4}               ;    Pop new task's CPSR
  196.         MSR     SPSR_cxsf, R4
  197.         
  198.         LDMFD   SP!, {R0-R12,LR,PC}^    ;    Pop new task's context
  199. ;*********************************************************************************************************
  200. ;                                      IRQ Interrupt Service Routine
  201. ;*********************************************************************************************************
  202. OS_CPU_IRQ_ISR
  203.         STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO IRQ STACK                     
  204.         
  205.         MOV     R1, SP                         ; Save   IRQ stack pointer
  206.         
  207.         ADD     SP, SP,#12                     ; Adjust IRQ stack pointer 
  208.         
  209.         SUB     R2, LR,#4                      ; Adjust PC for return address to task
  210.         MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
  211.         
  212.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  213.                                                ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
  214.         STMFD   SP!, {R2}                      ;    Push task's Return PC
  215.         STMFD   SP!, {LR}                      ;    Push task's LR
  216.         STMFD   SP!, {R4-R12}                  ;    Push task's R12-R4
  217.         
  218.         LDMFD   R1!, {R4-R6}                   ;    Move task's R1-R3 from IRQ stack to SVC stack
  219.         STMFD   SP!, {R4-R6}
  220.         STMFD   SP!, {R0}                      ;    Push task's R0    onto task's stack
  221.         STMFD   SP!, {R3}                      ;    Push task's CPSR (i.e. IRQ's SPSR)
  222.                 
  223.                                                ; HANDLE NESTING COUNTER
  224.         LDR     R0, =OSIntNesting              ; OSIntNesting++;
  225.         LDRB    R1, [R0]
  226.         ADD     R1, R1,#1
  227.         STRB    R1, [R0]
  228.         CMP     R1, #1                         ; if (OSIntNesting == 1) {
  229.         BNE     OS_CPU_IRQ_ISR_1
  230.         LDR     R4, =OSTCBCur                  ;     OSTCBCur->OSTCBStkPtr = SP
  231.         LDR     R5, [R4]
  232.         STR     SP, [R5]                       ; }
  233. OS_CPU_IRQ_ISR_1
  234.         MSR     CPSR_c, #(NO_INT | IRQ32_MODE) ; Change to IRQ mode (to use the IRQ stack to handle interrupt)
  235.         
  236. ;        LDR     R0, =OS_CPU_IRQ_ISR_Handler    ; OS_CPU_IRQ_ISR_Handler();
  237. ;        MOV     LR, PC
  238. ;        BX      R0            
  239. EIC_base_addr         EQU    0xFFFFF800; EIC base address.
  240. CICR_off_addr         EQU    0x04      ; Current Interrupt Channel Register.
  241. IVR_off_addr          EQU    0x18      ; Interrupt Vector Register.
  242. IPR_off_addr          EQU    0x40      ; Interrupt Pending Register.
  243.         LDR     R0, =(EIC_base_addr + IVR_off_addr)
  244.         MOV     LR, PC
  245.         BX      R0                             ; Branch to the IRQ handler.
  246.                                                ; Clear pending bit in EIC (using the proper IPRx)
  247.         LDR     R0, =EIC_base_addr
  248.         LDR     R2, [R0, #CICR_off_addr]       ; Get the IRQ channel number.
  249.         MOV     R3, #1
  250.         MOV     R3, R3, LSL r2
  251.         STR     R3, [R0, #IPR_off_addr]        ; Clear the corresponding IPR bit.
  252.         
  253.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  254.         
  255.         LDR     R0, =OSIntExit                 ; OSIntExit();
  256.         MOV     LR, PC
  257.         BX      R0            
  258.         
  259.                                                ; RESTORE NEW TASK'S CONTEXT
  260.         LDMFD   SP!, {R4}                      ;    Pop new task's CPSR
  261.         MSR     SPSR_cxsf, R4
  262.         
  263.         LDMFD   SP!, {R0-R12,LR,PC}^           ;    Pop new task's context
  264. ;*********************************************************************************************************
  265. ;                                      FIQ Interrupt Service Routine
  266. ;*********************************************************************************************************
  267. OS_CPU_FIQ_ISR
  268.                                         
  269.         STMFD   SP!, {R1-R3}                   ; PUSH WORKING REGISTERS ONTO FIQ STACK                     
  270.         
  271.         MOV     R1, SP                         ; Save   FIQ stack pointer
  272.         
  273.         ADD     SP, SP,#12                     ; Adjust FIQ stack pointer 
  274.         
  275.         SUB     R2, LR,#4                      ; Adjust PC for return address to task
  276.         MRS     R3, SPSR                       ; Copy SPSR (i.e. interrupted task's CPSR) to R3
  277.         
  278.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  279.                                                ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
  280.         STMFD   SP!, {R2}                      ;    Push task's Return PC
  281.         STMFD   SP!, {LR}                      ;    Push task's LR
  282.         STMFD   SP!, {R4-R12}                  ;    Push task's R12-R4
  283.         
  284.         LDMFD   R1!, {R4-R6}                   ;    Move task's R1-R3 from FIQ stack to SVC stack
  285.         STMFD   SP!, {R4-R6}
  286.         STMFD   SP!, {R0}                      ;    Push task's R0    onto task's stack
  287.         STMFD   SP!, {R3}                      ;    Push task's CPSR (i.e. FIQ's SPSR)
  288.                 
  289.                                                ; HANDLE NESTING COUNTER
  290.         LDR     R0, =OSIntNesting              ; OSIntNesting++;
  291.         LDRB    R1, [R0]
  292.         ADD     R1, R1,#1
  293.         STRB    R1, [R0]
  294.         CMP     R1, #1                         ; if (OSIntNesting == 1) {
  295.         BNE     OS_CPU_FIQ_ISR_1
  296.         LDR     R4, =OSTCBCur                  ;     OSTCBCur->OSTCBStkPtr = SP
  297.         LDR     R5, [R4]
  298.         STR     SP, [R5]                       ; }
  299. OS_CPU_FIQ_ISR_1
  300.         MSR     CPSR_c, #(NO_INT | FIQ32_MODE) ; Change to FIQ mode (to use the FIQ stack to handle interrupt)
  301.         
  302.         LDR     R0, =FIQ_Handler               ; FIQ_Handler();
  303.         MOV     LR, PC
  304.         BX      R0            
  305.         
  306.         MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; Change to SVC mode
  307.         
  308.         LDR     R0, =OSIntExit                 ; OSIntExit();
  309.         MOV     LR, PC
  310.         BX      R0            
  311.         
  312.                                                ; RESTORE NEW TASK'S CONTEXT
  313.         LDMFD   SP!, {R4}                      ;    Pop new task's CPSR
  314.         MSR     SPSR_cxsf, R4
  315.         
  316.         LDMFD   SP!, {R0-R12,LR,PC}^           ;    Pop new task's context
  317.         END