os_cpu_a.asm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. ;
  2. ;********************************************************************************************************
  3. ; uC/OS-III
  4. ; The Real-Time Kernel
  5. ;
  6. ;
  7. ; (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
  8. ; All rights reserved. Protected by international copyright laws.
  9. ;
  10. ; ARM Cortex-M3 Port
  11. ;
  12. ; File : OS_CPU_A.ASM
  13. ; Version : V3.01.2
  14. ; By : JJL
  15. ; BAN
  16. ;
  17. ; For : ARMv7M Cortex-M3
  18. ; Mode : Thumb2
  19. ; Toolchain : IAR EWARM
  20. ;********************************************************************************************************
  21. ;
  22. ;********************************************************************************************************
  23. ; PUBLIC FUNCTIONS
  24. ;********************************************************************************************************
  25. EXTERN OSRunning ; External references
  26. EXTERN OSPrioCur
  27. EXTERN OSPrioHighRdy
  28. EXTERN OSTCBCurPtr
  29. EXTERN OSTCBHighRdyPtr
  30. EXTERN OSIntExit
  31. EXTERN OSTaskSwHook
  32. EXTERN OS_CPU_ExceptStkBase
  33. EXPORT OSStartHighRdy ; Functions declared in this file
  34. EXPORT OS_CPU_PendSVHandler
  35. ;PAGE
  36. ;********************************************************************************************************
  37. ; EQUATES
  38. ;********************************************************************************************************
  39. NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register.
  40. NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14).
  41. NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest).
  42. NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
  43. ;********************************************************************************************************
  44. ; CODE GENERATION DIRECTIVES
  45. ;********************************************************************************************************
  46. ;RSEG CODE:CODE:NOROOT(2)
  47. ;THUMB
  48. PRESERVE8
  49. AREA |.text|,CODE,READONLY
  50. THUMB
  51. ;PAGE
  52. ;********************************************************************************************************
  53. ; START MULTITASKING
  54. ; void OSStartHighRdy(void)
  55. ;
  56. ; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
  57. ; the first task to start.
  58. ;
  59. ; 2) OSStartHighRdy() MUST:
  60. ; a) Setup PendSV exception priority to lowest;
  61. ; b) Set initial PSP to 0, to tell context switcher this is first run;
  62. ; c) Set the main stack to OS_CPU_ExceptStkBase
  63. ; d) Trigger PendSV exception;
  64. ; e) Enable interrupts (tasks will run with interrupts enabled).
  65. ;********************************************************************************************************
  66. OSStartHighRdy
  67. LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority
  68. LDR R1, =NVIC_PENDSV_PRI
  69. STRB R1, [R0]
  70. MOVS R0, #0 ; Set the PSP to 0 for initial context switch call
  71. MSR PSP, R0
  72. LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase
  73. LDR R1, [R0]
  74. MSR MSP, R1
  75. LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
  76. LDR R1, =NVIC_PENDSVSET
  77. STR R1, [R0]
  78. CPSIE I ; Enable interrupts at processor level
  79. OSStartHang
  80. B OSStartHang ; Should never get here
  81. ;PAGE
  82. ;********************************************************************************************************
  83. ; HANDLE PendSV EXCEPTION
  84. ; void OS_CPU_PendSVHandler(void)
  85. ;
  86. ; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
  87. ; context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the
  88. ; processor context on any exception, and restores same on return from exception. So only
  89. ; saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception
  90. ; this way means that context saving and restoring is identical whether it is initiated from
  91. ; a thread or occurs due to an interrupt or exception.
  92. ;
  93. ; 2) Pseudo-code is:
  94. ; a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
  95. ; b) Save remaining regs r4-r11 on process stack;
  96. ; c) Save the process SP in its TCB, OSTCBCurPtr->OSTCBStkPtr = SP;
  97. ; d) Call OSTaskSwHook();
  98. ; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
  99. ; f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
  100. ; g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->OSTCBStkPtr;
  101. ; h) Restore R4-R11 from new process stack;
  102. ; i) Perform exception return which will restore remaining context.
  103. ;
  104. ; 3) On entry into PendSV handler:
  105. ; a) The following have been saved on the process stack (by processor):
  106. ; xPSR, PC, LR, R12, R0-R3
  107. ; b) Processor mode is switched to Handler mode (from Thread mode)
  108. ; c) Stack is Main stack (switched from Process stack)
  109. ; d) OSTCBCurPtr points to the OS_TCB of the task to suspend
  110. ; OSTCBHighRdyPtr points to the OS_TCB of the task to resume
  111. ;
  112. ; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
  113. ; know that it will only be run when no other exception or interrupt is active, and
  114. ; therefore safe to assume that context being switched out was using the process stack (PSP).
  115. ;********************************************************************************************************
  116. OS_CPU_PendSVHandler
  117. CPSID I ; Prevent interruption during context switch
  118. MRS R0, PSP ; PSP is process stack pointer
  119. CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time
  120. SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
  121. STM R0, {R4-R11}
  122. LDR R1, =OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP;
  123. LDR R1, [R1]
  124. STR R0, [R1] ; R0 is SP of process being switched out
  125. ; At this point, entire context of process has been saved
  126. OS_CPU_PendSVHandler_nosave
  127. PUSH {R14} ; Save LR exc_return value
  128. LDR R0, =OSTaskSwHook ; OSTaskSwHook();
  129. BLX R0
  130. POP {R14}
  131. LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
  132. LDR R1, =OSPrioHighRdy
  133. LDRB R2, [R1]
  134. STRB R2, [R0]
  135. LDR R0, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
  136. LDR R1, =OSTCBHighRdyPtr
  137. LDR R2, [R1]
  138. STR R2, [R0]
  139. LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
  140. LDM R0, {R4-R11} ; Restore r4-11 from new process stack
  141. ADDS R0, R0, #0x20
  142. MSR PSP, R0 ; Load PSP with new process SP
  143. ORR LR, LR, #0x04 ; Ensure exception return uses process stack
  144. CPSIE I
  145. BX LR ; Exception return will restore remaining context
  146. END