portasm.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /*
  2. * FreeRTOS Kernel <DEVELOPMENT BRANCH>
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. /* Standard includes. */
  29. #include <stdint.h>
  30. /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
  31. * is defined correctly and privileged functions are placed in correct sections. */
  32. #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  33. /* Portasm includes. */
  34. #include "portasm.h"
  35. /* System call numbers includes. */
  36. #include "mpu_syscall_numbers.h"
  37. /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
  38. * header files. */
  39. #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  40. #if ( configENABLE_MPU == 1 )
  41. void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  42. {
  43. __asm volatile
  44. (
  45. " .extern pxCurrentTCB \n"
  46. " .syntax unified \n"
  47. " \n"
  48. " program_mpu_first_task: \n"
  49. " \n"
  50. " ldr r3, =pxCurrentTCB \n" /* r3 = &pxCurrentTCB. */
  51. " ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
  52. " adds r0, #4 \n" /* r0 = Second item in the TCB which is xMPUSettings. */
  53. " \n"
  54. " dmb \n" /* Complete outstanding transfers before disabling MPU. */
  55. " ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
  56. " ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
  57. " movs r3, #1 \n" /* r3 = 1. */
  58. " bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
  59. " str r2, [r1] \n" /* Disable MPU. */
  60. " \n"
  61. " ldr r1, =0xe000ed9c \n" /* r1 = 0xe000ed9c [Location of RBAR]. */
  62. " ldr r2, =0xe000eda0 \n" /* r2 = 0xe000eda0 [Location of RASR]. */
  63. " \n"
  64. " ldmia r0!, {r3-r4} \n" /* Read first set of RBAR/RASR registers from TCB. */
  65. " str r3, [r1] \n" /* Program RBAR. */
  66. " str r4, [r2] \n" /* Program RASR. */
  67. " \n"
  68. " ldmia r0!, {r3-r4} \n" /* Read second set of RBAR/RASR registers from TCB. */
  69. " str r3, [r1] \n" /* Program RBAR. */
  70. " str r4, [r2] \n" /* Program RASR. */
  71. " \n"
  72. " ldmia r0!, {r3-r4} \n" /* Read third set of RBAR/RASR registers from TCB. */
  73. " str r3, [r1] \n" /* Program RBAR. */
  74. " str r4, [r2] \n" /* Program RASR. */
  75. " \n"
  76. " ldmia r0!, {r3-r4} \n" /* Read fourth set of RBAR/RASR registers from TCB. */
  77. " str r3, [r1] \n" /* Program RBAR. */
  78. " str r4, [r2] \n" /* Program RASR. */
  79. " \n"
  80. " ldmia r0!, {r3-r4} \n" /* Read fifth set of RBAR/RASR registers from TCB. */
  81. " str r3, [r1] \n" /* Program RBAR. */
  82. " str r4, [r2] \n" /* Program RASR. */
  83. " \n"
  84. " ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
  85. " ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
  86. " movs r3, #1 \n" /* r3 = 1. */
  87. " orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
  88. " str r2, [r1] \n" /* Enable MPU. */
  89. " dsb \n" /* Force memory writes before continuing. */
  90. " \n"
  91. " restore_context_first_task: \n"
  92. " ldr r2, =pxCurrentTCB \n" /* r2 = &pxCurrentTCB. */
  93. " ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
  94. " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
  95. " \n"
  96. " restore_special_regs_first_task: \n"
  97. " subs r1, #12 \n"
  98. " ldmia r1!, {r2-r4} \n" /* r2 = original PSP, r3 = CONTROL, r4 = LR. */
  99. " subs r1, #12 \n"
  100. " msr psp, r2 \n"
  101. " msr control, r3 \n"
  102. " mov lr, r4 \n"
  103. " \n"
  104. " restore_general_regs_first_task: \n"
  105. " subs r1, #32 \n"
  106. " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
  107. " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
  108. " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
  109. " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
  110. " subs r1, #48 \n"
  111. " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */
  112. " mov r8, r4 \n" /* r8 = r4. */
  113. " mov r9, r5 \n" /* r9 = r5. */
  114. " mov r10, r6 \n" /* r10 = r6. */
  115. " mov r11, r7 \n" /* r11 = r7. */
  116. " subs r1, #32 \n"
  117. " ldmia r1!, {r4-r7} \n" /* Restore r4-r7. */
  118. " subs r1, #16 \n"
  119. " \n"
  120. " restore_context_done_first_task: \n"
  121. " str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
  122. " bx lr \n"
  123. " \n"
  124. " .align 4 \n"
  125. ::"i" ( portSVC_START_SCHEDULER ) : "memory"
  126. );
  127. }
  128. #else /* configENABLE_MPU */
  129. void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  130. {
  131. __asm volatile
  132. (
  133. " .extern pxCurrentTCB \n"
  134. " .syntax unified \n"
  135. " \n"
  136. " ldr r2, =pxCurrentTCB \n" /* r2 = &pxCurrentTCB. */
  137. " ldr r1, [r2] \n" /* r1 = pxCurrentTCB.*/
  138. " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
  139. " \n"
  140. " ldm r0!, {r2} \n" /* Read from stack - r2 = EXC_RETURN. */
  141. " movs r1, #2 \n" /* r1 = 2. */
  142. " msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
  143. " adds r0, #32 \n" /* Discard everything up to r0. */
  144. " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
  145. " isb \n"
  146. " bx r2 \n" /* Finally, branch to EXC_RETURN. */
  147. " \n"
  148. " .align 4 \n"
  149. );
  150. }
  151. #endif /* configENABLE_MPU */
  152. /*-----------------------------------------------------------*/
  153. BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
  154. {
  155. __asm volatile
  156. (
  157. " .syntax unified \n"
  158. " \n"
  159. " mrs r0, control \n" /* r0 = CONTROL. */
  160. " movs r1, #1 \n" /* r1 = 1. */
  161. " tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
  162. " beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */
  163. " movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
  164. " bx lr \n" /* Return. */
  165. " running_privileged: \n"
  166. " movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
  167. " bx lr \n" /* Return. */
  168. " \n"
  169. " .align 4 \n"
  170. ::: "r0", "r1", "memory"
  171. );
  172. }
  173. /*-----------------------------------------------------------*/
  174. void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  175. {
  176. __asm volatile
  177. (
  178. " .syntax unified \n"
  179. " \n"
  180. " mrs r0, control \n" /* Read the CONTROL register. */
  181. " movs r1, #1 \n" /* r1 = 1. */
  182. " bics r0, r1 \n" /* Clear the bit 0. */
  183. " msr control, r0 \n" /* Write back the new CONTROL value. */
  184. " bx lr \n" /* Return to the caller. */
  185. ::: "r0", "r1", "memory"
  186. );
  187. }
  188. /*-----------------------------------------------------------*/
  189. void vResetPrivilege( void ) /* __attribute__ (( naked )) */
  190. {
  191. __asm volatile
  192. (
  193. " .syntax unified \n"
  194. " \n"
  195. " mrs r0, control \n" /* r0 = CONTROL. */
  196. " movs r1, #1 \n" /* r1 = 1. */
  197. " orrs r0, r1 \n" /* r0 = r0 | r1. */
  198. " msr control, r0 \n" /* CONTROL = r0. */
  199. " bx lr \n" /* Return to the caller. */
  200. ::: "r0", "r1", "memory"
  201. );
  202. }
  203. /*-----------------------------------------------------------*/
  204. void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  205. {
  206. /* Don't reset the MSP stack as is done on CM3/4 devices. The reason is that
  207. * the Vector Table Offset Register (VTOR) is optional in CM0+ architecture
  208. * and therefore, may not be available on all the devices. */
  209. __asm volatile
  210. (
  211. " .syntax unified \n"
  212. " cpsie i \n" /* Globally enable interrupts. */
  213. " dsb \n"
  214. " isb \n"
  215. " svc %0 \n" /* System call to start the first task. */
  216. " nop \n"
  217. " \n"
  218. " .align 4 \n"
  219. ::"i" ( portSVC_START_SCHEDULER ) : "memory"
  220. );
  221. }
  222. /*-----------------------------------------------------------*/
  223. uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
  224. {
  225. __asm volatile
  226. (
  227. " .syntax unified \n"
  228. " \n"
  229. " mrs r0, PRIMASK \n"
  230. " cpsid i \n"
  231. " bx lr \n"
  232. ::: "memory"
  233. );
  234. }
  235. /*-----------------------------------------------------------*/
  236. void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
  237. {
  238. __asm volatile
  239. (
  240. " .syntax unified \n"
  241. " \n"
  242. " msr PRIMASK, r0 \n"
  243. " bx lr \n"
  244. ::: "memory"
  245. );
  246. }
  247. /*-----------------------------------------------------------*/
  248. #if ( configENABLE_MPU == 1 )
  249. void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  250. {
  251. __asm volatile
  252. (
  253. " .extern pxCurrentTCB \n"
  254. " .syntax unified \n"
  255. " \n"
  256. " ldr r2, =pxCurrentTCB \n" /* r2 = &( pxCurrentTCB ). */
  257. " ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
  258. " ldr r1, [r0] \n" /* r1 = Location in TCB where the context should be saved. */
  259. " mrs r2, psp \n" /* r2 = PSP. */
  260. " \n"
  261. " save_general_regs: \n"
  262. " stmia r1!, {r4-r7} \n" /* Store r4-r7. */
  263. " mov r4, r8 \n" /* r4 = r8. */
  264. " mov r5, r9 \n" /* r5 = r9. */
  265. " mov r6, r10 \n" /* r6 = r10. */
  266. " mov r7, r11 \n" /* r7 = r11. */
  267. " stmia r1!, {r4-r7} \n" /* Store r8-r11. */
  268. " ldmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context into r4-r7. */
  269. " stmia r1!, {r4-r7} \n" /* Store the hardware saved context. */
  270. " ldmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context into r4-r7. */
  271. " stmia r1!, {r4-r7} \n" /* Store the hardware saved context. */
  272. " \n"
  273. " save_special_regs: \n"
  274. " mrs r2, psp \n" /* r2 = PSP. */
  275. " mrs r3, control \n" /* r3 = CONTROL. */
  276. " mov r4, lr \n" /* r4 = LR. */
  277. " stmia r1!, {r2-r4} \n" /* Store original PSP (after hardware has saved context), CONTROL and LR. */
  278. " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
  279. " \n"
  280. " select_next_task: \n"
  281. " cpsid i \n"
  282. " bl vTaskSwitchContext \n"
  283. " cpsie i \n"
  284. " \n"
  285. " program_mpu: \n"
  286. " \n"
  287. " ldr r2, =pxCurrentTCB \n" /* r2 = &( pxCurrentTCB ). */
  288. " ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
  289. " adds r0, #4 \n" /* r0 = Second item in the TCB which is xMPUSettings. */
  290. " \n"
  291. " dmb \n" /* Complete outstanding transfers before disabling MPU. */
  292. " ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
  293. " ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
  294. " movs r3, #1 \n" /* r3 = 1. */
  295. " bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
  296. " str r2, [r1] \n" /* Disable MPU */
  297. " \n"
  298. " ldr r1, =0xe000ed9c \n" /* r1 = 0xe000ed9c [Location of RBAR]. */
  299. " ldr r2, =0xe000eda0 \n" /* r2 = 0xe000eda0 [Location of RASR]. */
  300. " \n"
  301. " ldmia r0!, {r3-r4} \n" /* Read first set of RBAR/RASR registers from TCB. */
  302. " str r3, [r1] \n" /* Program RBAR. */
  303. " str r4, [r2] \n" /* Program RASR. */
  304. " \n"
  305. " ldmia r0!, {r3-r4} \n" /* Read second set of RBAR/RASR registers from TCB. */
  306. " str r3, [r1] \n" /* Program RBAR. */
  307. " str r4, [r2] \n" /* Program RASR. */
  308. " \n"
  309. " ldmia r0!, {r3-r4} \n" /* Read third set of RBAR/RASR registers from TCB. */
  310. " str r3, [r1] \n" /* Program RBAR. */
  311. " str r4, [r2] \n" /* Program RASR. */
  312. " \n"
  313. " ldmia r0!, {r3-r4} \n" /* Read fourth set of RBAR/RASR registers from TCB. */
  314. " str r3, [r1] \n" /* Program RBAR. */
  315. " str r4, [r2] \n" /* Program RASR. */
  316. " \n"
  317. " ldmia r0!, {r3-r4} \n" /* Read fifth set of RBAR/RASR registers from TCB. */
  318. " str r3, [r1] \n" /* Program RBAR. */
  319. " str r4, [r2] \n" /* Program RASR. */
  320. " \n"
  321. " ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
  322. " ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
  323. " movs r3, #1 \n" /* r3 = 1. */
  324. " orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
  325. " str r2, [r1] \n" /* Enable MPU. */
  326. " dsb \n" /* Force memory writes before continuing. */
  327. " \n"
  328. " restore_context: \n"
  329. " ldr r2, =pxCurrentTCB \n" /* r2 = &pxCurrentTCB. */
  330. " ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
  331. " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
  332. " \n"
  333. " restore_special_regs: \n"
  334. " subs r1, #12 \n"
  335. " ldmia r1!, {r2-r4} \n" /* r2 = original PSP, r3 = CONTROL, r4 = LR. */
  336. " subs r1, #12 \n"
  337. " msr psp, r2 \n"
  338. " msr control, r3 \n"
  339. " mov lr, r4 \n"
  340. " \n"
  341. " restore_general_regs: \n"
  342. " subs r1, #32 \n"
  343. " ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
  344. " stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
  345. " ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
  346. " stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
  347. " subs r1, #48 \n"
  348. " ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */
  349. " mov r8, r4 \n" /* r8 = r4. */
  350. " mov r9, r5 \n" /* r9 = r5. */
  351. " mov r10, r6 \n" /* r10 = r6. */
  352. " mov r11, r7 \n" /* r11 = r7. */
  353. " subs r1, #32 \n"
  354. " ldmia r1!, {r4-r7} \n" /* Restore r4-r7. */
  355. " subs r1, #16 \n"
  356. " \n"
  357. " restore_context_done: \n"
  358. " str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
  359. " bx lr \n"
  360. " \n"
  361. " .align 4 \n"
  362. );
  363. }
  364. #else /* configENABLE_MPU */
  365. void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  366. {
  367. __asm volatile
  368. (
  369. " .extern pxCurrentTCB \n"
  370. " .syntax unified \n"
  371. " \n"
  372. " mrs r0, psp \n" /* Read PSP in r0. */
  373. " ldr r2, =pxCurrentTCB \n" /* r2 = &( pxCurrentTCB ). */
  374. " ldr r1, [r2] \n" /* r1 = pxCurrentTCB. */
  375. " subs r0, r0, #36 \n" /* Make space for LR and the remaining registers on the stack. */
  376. " str r0, [r1] \n" /* Save the new top of stack in TCB. */
  377. " \n"
  378. " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
  379. " stmia r0!, {r3-r7} \n" /* Store on the stack - LR and low registers that are not automatically saved. */
  380. " mov r4, r8 \n" /* r4 = r8. */
  381. " mov r5, r9 \n" /* r5 = r9. */
  382. " mov r6, r10 \n" /* r6 = r10. */
  383. " mov r7, r11 \n" /* r7 = r11. */
  384. " stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
  385. " \n"
  386. " cpsid i \n"
  387. " bl vTaskSwitchContext \n"
  388. " cpsie i \n"
  389. " \n"
  390. " ldr r2, =pxCurrentTCB \n" /* r2 = &( pxCurrentTCB ). */
  391. " ldr r1, [r2] \n" /* r1 = pxCurrentTCB. */
  392. " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
  393. " \n"
  394. " adds r0, r0, #20 \n" /* Move to the high registers. */
  395. " ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
  396. " mov r8, r4 \n" /* r8 = r4. */
  397. " mov r9, r5 \n" /* r9 = r5. */
  398. " mov r10, r6 \n" /* r10 = r6. */
  399. " mov r11, r7 \n" /* r11 = r7. */
  400. " msr psp, r0 \n" /* Remember the new top of stack for the task. */
  401. " subs r0, r0, #36 \n" /* Move to the starting of the saved context. */
  402. " ldmia r0!, {r3-r7} \n" /* Read from stack - r3 = LR and r4-r7 restored. */
  403. " bx r3 \n"
  404. " \n"
  405. " .align 4 \n"
  406. );
  407. }
  408. #endif /* configENABLE_MPU */
  409. /*-----------------------------------------------------------*/
  410. #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
  411. void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  412. {
  413. __asm volatile
  414. (
  415. " .syntax unified \n"
  416. " .extern vPortSVCHandler_C \n"
  417. " .extern vSystemCallEnter \n"
  418. " .extern vSystemCallExit \n"
  419. " .extern pxCurrentTCB \n"
  420. " \n"
  421. " movs r0, #4 \n"
  422. " mov r1, lr \n"
  423. " tst r0, r1 \n"
  424. " beq stack_on_msp \n"
  425. " \n"
  426. " stack_on_psp: \n"
  427. " mrs r0, psp \n"
  428. " b route_svc \n"
  429. " \n"
  430. " stack_on_msp: \n"
  431. " mrs r0, msp \n"
  432. " b route_svc \n"
  433. " \n"
  434. " route_svc: \n"
  435. " ldr r3, [r0, #24] \n"
  436. " subs r3, #2 \n"
  437. " ldrb r2, [r3, #0] \n"
  438. " ldr r3, =%0 \n"
  439. " cmp r2, r3 \n"
  440. " blt system_call_enter \n"
  441. " ldr r3, =%1 \n"
  442. " cmp r2, r3 \n"
  443. " beq system_call_exit \n"
  444. " ldr r3, =vPortSVCHandler_C \n"
  445. " bx r3 \n"
  446. " \n"
  447. " system_call_enter: \n"
  448. " push {lr} \n"
  449. " bl vSystemCallEnter \n"
  450. " pop {pc} \n"
  451. " \n"
  452. " system_call_exit: \n"
  453. " push {lr} \n"
  454. " bl vSystemCallExit \n"
  455. " pop {pc} \n"
  456. " \n"
  457. " .align 4 \n"
  458. " \n"
  459. : /* No outputs. */
  460. : "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
  461. : "r0", "r1", "r2", "r3", "memory"
  462. );
  463. }
  464. #else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
  465. void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
  466. {
  467. __asm volatile
  468. (
  469. " .syntax unified \n"
  470. " .extern vPortSVCHandler_C \n"
  471. " \n"
  472. " movs r0, #4 \n"
  473. " mov r1, lr \n"
  474. " tst r0, r1 \n"
  475. " beq stacking_used_msp \n"
  476. " \n"
  477. " stacking_used_psp: \n"
  478. " mrs r0, psp \n"
  479. " ldr r3, =vPortSVCHandler_C \n"
  480. " bx r3 \n"
  481. " \n"
  482. " stacking_used_msp: \n"
  483. " mrs r0, msp \n"
  484. " ldr r3, =vPortSVCHandler_C \n"
  485. " bx r3 \n"
  486. " \n"
  487. " .align 4 \n"
  488. );
  489. }
  490. #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
  491. /*-----------------------------------------------------------*/