irq_armv7m.s 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. ;/*
  2. ; * Copyright (c) 2013-2023 Arm Limited. All rights reserved.
  3. ; *
  4. ; * SPDX-License-Identifier: Apache-2.0
  5. ; *
  6. ; * Licensed under the Apache License, Version 2.0 (the License); you may
  7. ; * not use this file except in compliance with the License.
  8. ; * You may obtain a copy of the License at
  9. ; *
  10. ; * www.apache.org/licenses/LICENSE-2.0
  11. ; *
  12. ; * Unless required by applicable law or agreed to in writing, software
  13. ; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. ; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ; * See the License for the specific language governing permissions and
  16. ; * limitations under the License.
  17. ; *
  18. ; * -----------------------------------------------------------------------------
  19. ; *
  20. ; * Project: CMSIS-RTOS RTX
  21. ; * Title: ARMv7-M Exception handlers
  22. ; *
  23. ; * -----------------------------------------------------------------------------
  24. ; */
  25. NAME irq_armv7m.s
  26. #include "rtx_def.h"
  27. #ifdef __ARMVFP__
  28. FPU_USED EQU 1
  29. #else
  30. FPU_USED EQU 0
  31. #endif
  32. I_T_RUN_OFS EQU 20 ; osRtxInfo.thread.run offset
  33. TCB_SP_OFS EQU 56 ; TCB.SP offset
  34. TCB_SF_OFS EQU 34 ; TCB.stack_frame offset
  35. TCB_ZONE_OFS EQU 68 ; TCB.zone offset
  36. FPCCR EQU 0xE000EF34 ; FPCCR Address
  37. osRtxErrorStackOverflow\
  38. EQU 1 ; Stack overflow
  39. osRtxErrorSVC EQU 6 ; Invalid SVC function called
  40. PRESERVE8
  41. SECTION .rodata:DATA:NOROOT(2)
  42. EXPORT irqRtxLib
  43. irqRtxLib DCB 0 ; Non weak library reference
  44. THUMB
  45. SECTION .text:CODE:NOROOT(2)
  46. SVC_Handler
  47. EXPORT SVC_Handler
  48. IMPORT osRtxUserSVC
  49. IMPORT osRtxInfo
  50. #ifdef RTX_STACK_CHECK
  51. IMPORT osRtxThreadStackCheck
  52. IMPORT osRtxKernelErrorNotify
  53. #endif
  54. #ifdef RTX_SVC_PTR_CHECK
  55. IMPORT |Image$$RTX_SVC_VENEERS$$Base|
  56. IMPORT |Image$$RTX_SVC_VENEERS$$Length|
  57. IMPORT osRtxKernelErrorNotify
  58. #endif
  59. #ifdef RTX_EXECUTION_ZONE
  60. IMPORT osZoneSetup_Callback
  61. #endif
  62. TST LR,#0x04 ; Determine return stack from EXC_RETURN bit 2
  63. ITE EQ
  64. MRSEQ R0,MSP ; Get MSP if return stack is MSP
  65. MRSNE R0,PSP ; Get PSP if return stack is PSP
  66. LDR R1,[R0,#24] ; Load saved PC from stack
  67. LDRB R1,[R1,#-2] ; Load SVC number
  68. CMP R1,#0 ; Check SVC number
  69. BNE SVC_User ; Branch if not SVC 0
  70. #ifdef RTX_SVC_PTR_CHECK
  71. LDR R12,[R0,#16] ; Load function address from stack
  72. SUB R1,R12,#1 ; Clear T-bit of function address
  73. LSLS R2,R1,#30 ; Check if 4-byte aligned
  74. BEQ SVC_PtrBoundsCheck ; Branch if address is aligned
  75. SVC_PtrInvalid
  76. PUSH {R0,LR} ; Save SP and EXC_RETURN
  77. MOVS R0,#osRtxErrorSVC ; Parameter: code
  78. MOV R1,R12 ; Parameter: object_id
  79. BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify
  80. POP {R12,LR} ; Restore SP and EXC_RETURN
  81. B SVC_Context ; Branch to context handling
  82. SVC_PtrBoundsCheck
  83. LDR R2,=|Image$$RTX_SVC_VENEERS$$Base|
  84. LDR R3,=|Image$$RTX_SVC_VENEERS$$Length|
  85. SUBS R2,R1,R2 ; Subtract SVC table base address
  86. CMP R2,R3 ; Compare with SVC table boundaries
  87. BHS SVC_PtrInvalid ; Branch if address is out of bounds
  88. #endif
  89. PUSH {R0,LR} ; Save SP and EXC_RETURN
  90. LDM R0,{R0-R3,R12} ; Load function parameters and address from stack
  91. BLX R12 ; Call service function
  92. POP {R12,LR} ; Restore SP and EXC_RETURN
  93. STR R0,[R12] ; Store function return value
  94. SVC_Context
  95. LDR R3,=osRtxInfo+I_T_RUN_OFS; Load address of osRtxInfo.thread.run
  96. LDM R3,{R1,R2} ; Load osRtxInfo.thread.run: curr & next
  97. CMP R1,R2 ; Check if thread switch is required
  98. IT EQ
  99. BXEQ LR ; Exit when threads are the same
  100. STR R2,[R3] ; osRtxInfo.thread.run: curr = next
  101. #if (FPU_USED != 0)
  102. CBNZ R1,SVC_ContextSave ; Branch if running thread is not deleted
  103. SVC_FP_LazyState
  104. TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
  105. BNE SVC_ContextRestore ; Branch if not extended stack frame
  106. LDR R3,=FPCCR ; FPCCR Address
  107. LDR R0,[R3] ; Load FPCCR
  108. BIC R0,R0,#1 ; Clear LSPACT (Lazy state preservation)
  109. STR R0,[R3] ; Store FPCCR
  110. B SVC_ContextRestore ; Branch to context restore handling
  111. #else
  112. CBZ R1,SVC_ContextRestore ; Branch if running thread is deleted
  113. #endif
  114. SVC_ContextSave
  115. #ifdef RTX_STACK_CHECK
  116. SUB R12,R12,#32 ; Calculate SP: space for R4..R11
  117. #if (FPU_USED != 0)
  118. TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
  119. IT EQ ; If extended stack frame
  120. SUBEQ R12,R12,#64 ; Additional space for S16..S31
  121. STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
  122. #endif
  123. STR R12,[R1,#TCB_SP_OFS] ; Store SP
  124. PUSH {R1,R2} ; Save osRtxInfo.thread.run: curr & next
  125. MOV R0,R1 ; Parameter: osRtxInfo.thread.run.curr
  126. BL osRtxThreadStackCheck ; Check if thread stack is overrun
  127. POP {R1,R2} ; Restore osRtxInfo.thread.run: curr & next
  128. CBNZ R0,SVC_ContextSaveRegs ; Branch when stack check is ok
  129. #if (FPU_USED != 0)
  130. MOV R4,R1 ; Assign osRtxInfo.thread.run.curr to R4
  131. #endif
  132. MOVS R0,#osRtxErrorStackOverflow ; Parameter: r0=code, r1=object_id
  133. BL osRtxKernelErrorNotify ; Call osRtxKernelErrorNotify
  134. LDR R3,=osRtxInfo+I_T_RUN_OFS ; Load address of osRtxInfo.thread.run
  135. LDR R2,[R3,#4] ; Load osRtxInfo.thread.run: next
  136. STR R2,[R3] ; osRtxInfo.thread.run: curr = next
  137. MOVS R1,#0 ; Simulate deleted running thread
  138. #if (FPU_USED != 0)
  139. LDRSB LR,[R4,#TCB_SF_OFS] ; Load stack frame information
  140. B SVC_FP_LazyState ; Branch to FP lazy state handling
  141. #else
  142. B SVC_ContextRestore ; Branch to context restore handling
  143. #endif
  144. SVC_ContextSaveRegs
  145. LDR R12,[R1,#TCB_SP_OFS] ; Load SP
  146. #if (FPU_USED != 0)
  147. LDRSB LR, [R1,#TCB_SF_OFS] ; Load stack frame information
  148. TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
  149. IT EQ ; If extended stack frame
  150. VSTMIAEQ R12!,{S16-S31} ; Save VFP S16..S31
  151. #endif
  152. STM R12,{R4-R11} ; Save R4..R11
  153. #else
  154. STMDB R12!,{R4-R11} ; Save R4..R11
  155. #if (FPU_USED != 0)
  156. TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
  157. IT EQ ; If extended stack frame
  158. VSTMDBEQ R12!,{S16-S31} ; Save VFP S16.S31
  159. STRB LR, [R1,#TCB_SF_OFS] ; Store stack frame information
  160. #endif
  161. STR R12,[R1,#TCB_SP_OFS] ; Store SP
  162. #endif
  163. SVC_ContextRestore
  164. MOVS R4,R2 ; Assign osRtxInfo.thread.run.next to R4, clear Z flag
  165. #ifdef RTX_EXECUTION_ZONE
  166. LDRB R0,[R2,#TCB_ZONE_OFS] ; Load osRtxInfo.thread.run.next: zone
  167. CBZ R1,SVC_ZoneSetup ; Branch if running thread is deleted (Z flag unchanged)
  168. LDRB R1,[R1,#TCB_ZONE_OFS] ; Load osRtxInfo.thread.run.curr: zone
  169. CMP R0,R1 ; Check if next:zone == curr:zone
  170. SVC_ZoneSetup
  171. IT NE ; If zone has changed or running thread is deleted
  172. BLNE osZoneSetup_Callback ; Setup zone for next thread
  173. #endif
  174. LDR R0,[R4,#TCB_SP_OFS] ; Load SP
  175. #if (FPU_USED != 0)
  176. LDRSB LR,[R4,#TCB_SF_OFS] ; Load stack frame information
  177. TST LR,#0x10 ; Determine stack frame from EXC_RETURN bit 4
  178. IT EQ ; If extended stack frame
  179. VLDMIAEQ R0!,{S16-S31} ; Restore VFP S16..S31
  180. #else
  181. MVN LR,#~0xFFFFFFFD ; Set EXC_RETURN value
  182. #endif
  183. LDMIA R0!,{R4-R11} ; Restore R4..R11
  184. MSR PSP,R0 ; Set PSP
  185. SVC_Exit
  186. BX LR ; Exit from handler
  187. SVC_User
  188. LDR R2,=osRtxUserSVC ; Load address of SVC table
  189. LDR R3,[R2] ; Load SVC maximum number
  190. CMP R1,R3 ; Check SVC number range
  191. BHI SVC_Exit ; Branch if out of range
  192. PUSH {R0,LR} ; Save SP and EXC_RETURN
  193. LDR R12,[R2,R1,LSL #2] ; Load address of SVC function
  194. LDM R0,{R0-R3} ; Load function parameters from stack
  195. BLX R12 ; Call service function
  196. POP {R12,LR} ; Restore SP and EXC_RETURN
  197. STR R0,[R12] ; Store function return value
  198. BX LR ; Return from handler
  199. PendSV_Handler
  200. EXPORT PendSV_Handler
  201. IMPORT osRtxPendSV_Handler
  202. PUSH {R0,LR} ; Save EXC_RETURN
  203. BL osRtxPendSV_Handler ; Call osRtxPendSV_Handler
  204. POP {R0,LR} ; Restore EXC_RETURN
  205. MRS R12,PSP ; Save PSP to R12
  206. B SVC_Context ; Branch to context handling
  207. SysTick_Handler
  208. EXPORT SysTick_Handler
  209. IMPORT osRtxTick_Handler
  210. PUSH {R0,LR} ; Save EXC_RETURN
  211. BL osRtxTick_Handler ; Call osRtxTick_Handler
  212. POP {R0,LR} ; Restore EXC_RETURN
  213. MRS R12,PSP ; Save PSP to R12
  214. B SVC_Context ; Branch to context handling
  215. #ifdef RTX_SAFETY_FEATURES
  216. osFaultResume PROC
  217. EXPORT osFaultResume
  218. MRS R12,PSP ; Save PSP to R12
  219. B SVC_Context ; Branch to context handling
  220. ALIGN
  221. ENDP
  222. #endif
  223. END