No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 

366 líneas
17 KiB

  1. ;********************************************************************************************************
  2. ; uC/OS-II
  3. ; The Real-Time Kernel
  4. ;
  5. ; Copyright 1992-2021 Silicon Laboratories Inc. www.silabs.com
  6. ;
  7. ; SPDX-License-Identifier: APACHE-2.0
  8. ;
  9. ; This software is subject to an open source license and is distributed by
  10. ; Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  11. ; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  12. ;
  13. ;********************************************************************************************************
  14. ;********************************************************************************************************
  15. ;
  16. ; ARMv7-M Port
  17. ;
  18. ; Filename : os_cpu_a.asm
  19. ; Version : V2.93.01
  20. ;********************************************************************************************************
  21. ; For : ARMv7-M Cortex-M
  22. ; Mode : Thumb-2 ISA
  23. ; Toolchain : IAR EWARM
  24. ;********************************************************************************************************
  25. ; Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures.
  26. ; (2) It has been tested with the following Hardware Floating Point Unit.
  27. ; (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M
  28. ; (b) Double-precision: FPv5-D16-M
  29. ;********************************************************************************************************
  30. ;********************************************************************************************************
  31. ; PUBLIC FUNCTIONS
  32. ;********************************************************************************************************
  33. EXTERN OSRunning ; External references
  34. EXTERN OSPrioCur
  35. EXTERN OSPrioHighRdy
  36. EXTERN OSTCBCur
  37. EXTERN OSTCBHighRdy
  38. EXTERN OSIntExit
  39. EXTERN OSTaskSwHook
  40. EXTERN OS_CPU_ExceptStkBase
  41. EXTERN OS_KA_BASEPRI_Boundary
  42. PUBLIC OSStartHighRdy ; Functions declared in this file
  43. PUBLIC OS_CPU_SR_Save
  44. PUBLIC OS_CPU_SR_Restore
  45. PUBLIC OSCtxSw
  46. PUBLIC OSIntCtxSw
  47. PUBLIC PendSV_Handler
  48. #ifdef __ARMVFP__
  49. PUBLIC OS_CPU_FP_Reg_Push
  50. PUBLIC OS_CPU_FP_Reg_Pop
  51. #endif
  52. ;********************************************************************************************************
  53. ; EQUATES
  54. ;********************************************************************************************************
  55. NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register.
  56. NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14).
  57. NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest).
  58. NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
  59. ;********************************************************************************************************
  60. ; CODE GENERATION DIRECTIVES
  61. ;********************************************************************************************************
  62. RSEG CODE:CODE:NOROOT(2)
  63. THUMB
  64. ;********************************************************************************************************
  65. ; FLOATING POINT REGISTERS PUSH
  66. ; void OS_CPU_FP_Reg_Push (OS_STK *stkPtr)
  67. ;
  68. ; Note(s) : 1) This function saves S16-S31 registers of the Floating Point Unit.
  69. ;
  70. ; 2) Pseudo-code is:
  71. ; a) Push remaining FPU regs S16-S31 on process stack;
  72. ; b) Update OSTCBCur->OSTCBStkPtr;
  73. ;********************************************************************************************************
  74. #ifdef __ARMVFP__
  75. OS_CPU_FP_Reg_Push
  76. MRS R1, PSP ; PSP is process stack pointer
  77. CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time
  78. VSTMDB R0!, {S16-S31}
  79. LDR R1, =OSTCBCur
  80. LDR R2, [R1]
  81. STR R0, [R2]
  82. OS_CPU_FP_nosave
  83. BX LR
  84. #endif
  85. ;********************************************************************************************************
  86. ; FLOATING POINT REGISTERS POP
  87. ; void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr)
  88. ;
  89. ; Note(s) : 1) This function restores S16-S31 of the Floating Point Unit.
  90. ;
  91. ; 2) Pseudo-code is:
  92. ; a) Restore regs S16-S31 of new process stack;
  93. ; b) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack;
  94. ;********************************************************************************************************
  95. #ifdef __ARMVFP__
  96. OS_CPU_FP_Reg_Pop
  97. VLDMIA R0!, {S16-S31}
  98. LDR R1, =OSTCBHighRdy
  99. LDR R2, [R1]
  100. STR R0, [R2]
  101. BX LR
  102. #endif
  103. ;********************************************************************************************************
  104. ; CRITICAL SECTION METHOD 3 FUNCTIONS
  105. ;
  106. ; Description : Disable/Enable Kernel aware interrupts by preserving the state of BASEPRI. Generally speaking,
  107. ; the state of the BASEPRI interrupt exception processing is stored in the local variable
  108. ; 'cpu_sr' & Kernel Aware interrupts are then disabled ('cpu_sr' is allocated in all functions
  109. ; that need to disable Kernel aware interrupts). The previous BASEPRI interrupt state is restored
  110. ; by copying 'cpu_sr' into the BASEPRI register.
  111. ;
  112. ; Prototypes : OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri);
  113. ; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
  114. ;
  115. ;
  116. ; Note(s) : 1) These functions are used in general like this:
  117. ;
  118. ; void Task (void *p_arg)
  119. ; {
  120. ; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
  121. ; OS_CPU_SR cpu_sr;
  122. ; #endif
  123. ;
  124. ; :
  125. ; :
  126. ; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SR_Save(new_basepri); */
  127. ; :
  128. ; :
  129. ; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */
  130. ; :
  131. ; :
  132. ; }
  133. ;
  134. ; 2) Increasing priority using a write to BASEPRI does not take effect immediately.
  135. ; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI
  136. ; might incorrectly be preempted by an insufficient high priority exception.
  137. ;
  138. ; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence:
  139. ;
  140. ; CPSID i
  141. ; MSR to BASEPRI
  142. ; DSB
  143. ; ISB
  144. ; CPSIE i
  145. ;********************************************************************************************************
  146. OS_CPU_SR_Save
  147. CPSID I ; Cortex-M7 errata notice. See Note #2
  148. PUSH {R1}
  149. MRS R1, BASEPRI
  150. MSR BASEPRI, R0
  151. DSB
  152. ISB
  153. MOV R0, R1
  154. POP {R1}
  155. CPSIE I
  156. BX LR
  157. OS_CPU_SR_Restore
  158. CPSID I ; Cortex-M7 errata notice. See Note #2
  159. MSR BASEPRI, R0
  160. DSB
  161. ISB
  162. CPSIE I
  163. BX LR
  164. ;********************************************************************************************************
  165. ; START MULTITASKING
  166. ; void OSStartHighRdy(void)
  167. ;
  168. ; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
  169. ; the first task to start.
  170. ;
  171. ; 2) During task execution, PSP is used as the stack pointer.
  172. ; When an exception occurs, the core will switch to MSP until the exception return.
  173. ;
  174. ; 3) OSStartHighRdy() MUST:
  175. ; a) Setup PendSV exception priority to lowest;
  176. ; b) Set initial PSP to 0, to tell context switcher this is first run;
  177. ; c) Set the main stack to OS_CPU_ExceptStkBase
  178. ; d) Set OSRunning to TRUE;
  179. ; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
  180. ; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
  181. ; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
  182. ; h) Restore R0-R11 and R14 from new process stack;
  183. ; i) Enable interrupts (tasks will run with interrupts enabled).
  184. ;********************************************************************************************************
  185. OSStartHighRdy
  186. CPSID I ; Prevent interruption during context switch
  187. LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority
  188. LDR R1, =NVIC_PENDSV_PRI
  189. STRB R1, [R0]
  190. MOVS R0, #0 ; Set the PSP to 0 for initial context switch call
  191. MSR PSP, R0
  192. LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase
  193. LDR R1, [R0]
  194. MSR MSP, R1
  195. BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop
  196. LDR R0, =OSRunning ; OSRunning = TRUE
  197. MOVS R1, #1
  198. STRB R1, [R0]
  199. LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
  200. LDR R1, =OSPrioHighRdy
  201. LDRB R2, [R1]
  202. STRB R2, [R0]
  203. LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
  204. LDR R1, =OSTCBHighRdy
  205. LDR R2, [R1]
  206. STR R2, [R0]
  207. LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
  208. MSR PSP, R0 ; Load PSP with new process SP
  209. MRS R0, CONTROL
  210. ORR R0, R0, #2
  211. MSR CONTROL, R0
  212. ISB ; Sync instruction stream
  213. LDMFD SP!, {R4-R11, LR} ; Restore r4-11, lr from new process stack
  214. LDMFD SP!, {R0-R3} ; Restore r0, r3
  215. LDMFD SP!, {R12, LR} ; Load R12 and LR
  216. LDMFD SP!, {R1, R2} ; Load PC and discard xPSR
  217. CPSIE I
  218. BX R1
  219. ;********************************************************************************************************
  220. ; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
  221. ; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
  222. ;
  223. ; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function
  224. ; triggers the PendSV exception which is where the real work is done.
  225. ;
  226. ; 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
  227. ; the result of an interrupt. This function simply triggers a PendSV exception which will
  228. ; be handled when there are no more interrupts active and interrupts are enabled.
  229. ;********************************************************************************************************
  230. OSCtxSw
  231. OSIntCtxSw
  232. LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
  233. LDR R1, =NVIC_PENDSVSET
  234. STR R1, [R0]
  235. BX LR
  236. ;********************************************************************************************************
  237. ; HANDLE PendSV EXCEPTION
  238. ; void OS_CPU_PendSVHandler(void)
  239. ;
  240. ; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
  241. ; context switches with Cortex-M. This is because the Cortex-M auto-saves half of the
  242. ; processor context on any exception, and restores same on return from exception. So only
  243. ; saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception
  244. ; this way means that context saving and restoring is identical whether it is initiated from
  245. ; a thread or occurs due to an interrupt or exception.
  246. ;
  247. ; 2) Pseudo-code is:
  248. ; a) Get the process SP
  249. ; b) Save remaining regs r4-r11 & r14 on process stack;
  250. ; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
  251. ; d) Call OSTaskSwHook();
  252. ; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
  253. ; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
  254. ; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
  255. ; h) Restore R4-R11 and R14 from new process stack;
  256. ; i) Perform exception return which will restore remaining context.
  257. ;
  258. ; 3) On entry into PendSV handler:
  259. ; a) The following have been saved on the process stack (by processor):
  260. ; xPSR, PC, LR, R12, R0-R3
  261. ; b) Processor mode is switched to Handler mode (from Thread mode)
  262. ; c) Stack is Main stack (switched from Process stack)
  263. ; d) OSTCBCur points to the OS_TCB of the task to suspend
  264. ; OSTCBHighRdy points to the OS_TCB of the task to resume
  265. ;
  266. ; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
  267. ; know that it will only be run when no other exception or interrupt is active, and
  268. ; therefore safe to assume that context being switched out was using the process stack (PSP).
  269. ;
  270. ; 5) Increasing priority using a write to BASEPRI does not take effect immediately.
  271. ; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI
  272. ; might incorrectly be preempted by an insufficient high priority exception.
  273. ;
  274. ; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence:
  275. ;
  276. ; CPSID i
  277. ; MSR to BASEPRI
  278. ; DSB
  279. ; ISB
  280. ; CPSIE i
  281. ;********************************************************************************************************
  282. PendSV_Handler
  283. CPSID I ; Cortex-M7 errata notice. See Note #5
  284. MOV32 R2, OS_KA_BASEPRI_Boundary ; Set BASEPRI priority level required for exception preemption
  285. LDR R1, [R2]
  286. MSR BASEPRI, R1
  287. DSB
  288. ISB
  289. CPSIE I
  290. MRS R0, PSP ; PSP is process stack pointer
  291. STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack
  292. LDR R5, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
  293. LDR R1, [R5]
  294. STR R0, [R1] ; R0 is SP of process being switched out
  295. ; At this point, entire context of process has been saved
  296. MOV R4, LR ; Save LR exc_return value
  297. BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop
  298. LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
  299. LDR R1, =OSPrioHighRdy
  300. LDRB R2, [R1]
  301. STRB R2, [R0]
  302. LDR R1, =OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy;
  303. LDR R2, [R1]
  304. STR R2, [R5]
  305. ORR LR, R4, #0x04 ; Ensure exception return uses process stack
  306. LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
  307. LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack
  308. MSR PSP, R0 ; Load PSP with new process SP
  309. MOV32 R2, #0 ; Restore BASEPRI priority level to 0
  310. CPSID I
  311. MSR BASEPRI, R2
  312. DSB
  313. ISB
  314. CPSIE I
  315. BX LR ; Exception return will restore remaining context
  316. END