portasm.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. /* FreeRTOS includes. */
  29. #include "FreeRTOSConfig.h"
  30. /* Xilinx library includes. */
  31. #include "microblaze_exceptions_g.h"
  32. #include "xparameters.h"
  33. #include "microblaze_instructions.h"
  34. /* The context is oversized to allow functions called from the ISR to write
  35. back into the caller stack. */
  36. #if defined (__arch64__)
  37. #if( XPAR_MICROBLAZE_USE_FPU != 0 )
  38. #define portCONTEXT_SIZE 272
  39. #define portMINUS_CONTEXT_SIZE -272
  40. #else
  41. #define portCONTEXT_SIZE 264
  42. #define portMINUS_CONTEXT_SIZE -264
  43. #endif
  44. #else
  45. #if( XPAR_MICROBLAZE_USE_FPU != 0 )
  46. #define portCONTEXT_SIZE 136
  47. #define portMINUS_CONTEXT_SIZE -136
  48. #else
  49. #define portCONTEXT_SIZE 132
  50. #define portMINUS_CONTEXT_SIZE -132
  51. #endif
  52. #endif
  53. /* Offsets from the stack pointer at which saved registers are placed. */
  54. #if defined (__arch64__)
  55. #define portR31_OFFSET 8
  56. #define portR30_OFFSET 16
  57. #define portR29_OFFSET 24
  58. #define portR28_OFFSET 32
  59. #define portR27_OFFSET 40
  60. #define portR26_OFFSET 48
  61. #define portR25_OFFSET 56
  62. #define portR24_OFFSET 64
  63. #define portR23_OFFSET 72
  64. #define portR22_OFFSET 80
  65. #define portR21_OFFSET 88
  66. #define portR20_OFFSET 96
  67. #define portR19_OFFSET 104
  68. #define portR18_OFFSET 112
  69. #define portR17_OFFSET 120
  70. #define portR16_OFFSET 128
  71. #define portR15_OFFSET 136
  72. #define portR14_OFFSET 144
  73. #define portR13_OFFSET 152
  74. #define portR12_OFFSET 160
  75. #define portR11_OFFSET 168
  76. #define portR10_OFFSET 176
  77. #define portR9_OFFSET 184
  78. #define portR8_OFFSET 192
  79. #define portR7_OFFSET 200
  80. #define portR6_OFFSET 208
  81. #define portR5_OFFSET 216
  82. #define portR4_OFFSET 224
  83. #define portR3_OFFSET 232
  84. #define portR2_OFFSET 240
  85. #define portCRITICAL_NESTING_OFFSET 248
  86. #define portMSR_OFFSET 256
  87. #define portFSR_OFFSET 264
  88. #else
  89. #define portR31_OFFSET 4
  90. #define portR30_OFFSET 8
  91. #define portR29_OFFSET 12
  92. #define portR28_OFFSET 16
  93. #define portR27_OFFSET 20
  94. #define portR26_OFFSET 24
  95. #define portR25_OFFSET 28
  96. #define portR24_OFFSET 32
  97. #define portR23_OFFSET 36
  98. #define portR22_OFFSET 40
  99. #define portR21_OFFSET 44
  100. #define portR20_OFFSET 48
  101. #define portR19_OFFSET 52
  102. #define portR18_OFFSET 56
  103. #define portR17_OFFSET 60
  104. #define portR16_OFFSET 64
  105. #define portR15_OFFSET 68
  106. #define portR14_OFFSET 72
  107. #define portR13_OFFSET 76
  108. #define portR12_OFFSET 80
  109. #define portR11_OFFSET 84
  110. #define portR10_OFFSET 88
  111. #define portR9_OFFSET 92
  112. #define portR8_OFFSET 96
  113. #define portR7_OFFSET 100
  114. #define portR6_OFFSET 104
  115. #define portR5_OFFSET 108
  116. #define portR4_OFFSET 112
  117. #define portR3_OFFSET 116
  118. #define portR2_OFFSET 120
  119. #define portCRITICAL_NESTING_OFFSET 124
  120. #define portMSR_OFFSET 128
  121. #define portFSR_OFFSET 132
  122. #endif
  123. .extern pxCurrentTCB
  124. .extern XIntc_DeviceInterruptHandler
  125. .extern vTaskSwitchContext
  126. .extern uxCriticalNesting
  127. .extern pulISRStack
  128. .extern ulTaskSwitchRequested
  129. .extern vPortExceptionHandler
  130. .extern pulStackPointerOnFunctionEntry
  131. .global _interrupt_handler
  132. .global VPortYieldASM
  133. .global vPortStartFirstTask
  134. .global vPortExceptionHandlerEntry
  135. .macro portSAVE_CONTEXT
  136. /* Make room for the context on the stack. */
  137. ADDLIK r1, r1, portMINUS_CONTEXT_SIZE
  138. /* Stack general registers. */
  139. SI r31, r1, portR31_OFFSET
  140. SI r30, r1, portR30_OFFSET
  141. SI r29, r1, portR29_OFFSET
  142. SI r28, r1, portR28_OFFSET
  143. SI r27, r1, portR27_OFFSET
  144. SI r26, r1, portR26_OFFSET
  145. SI r25, r1, portR25_OFFSET
  146. SI r24, r1, portR24_OFFSET
  147. SI r23, r1, portR23_OFFSET
  148. SI r22, r1, portR22_OFFSET
  149. SI r21, r1, portR21_OFFSET
  150. SI r20, r1, portR20_OFFSET
  151. SI r19, r1, portR19_OFFSET
  152. SI r18, r1, portR18_OFFSET
  153. SI r17, r1, portR17_OFFSET
  154. SI r16, r1, portR16_OFFSET
  155. SI r15, r1, portR15_OFFSET
  156. /* R14 is saved later as it needs adjustment if a yield is performed. */
  157. SI r13, r1, portR13_OFFSET
  158. SI r12, r1, portR12_OFFSET
  159. SI r11, r1, portR11_OFFSET
  160. SI r10, r1, portR10_OFFSET
  161. SI r9, r1, portR9_OFFSET
  162. SI r8, r1, portR8_OFFSET
  163. SI r7, r1, portR7_OFFSET
  164. SI r6, r1, portR6_OFFSET
  165. SI r5, r1, portR5_OFFSET
  166. SI r4, r1, portR4_OFFSET
  167. SI r3, r1, portR3_OFFSET
  168. SI r2, r1, portR2_OFFSET
  169. /* Stack the critical section nesting value. */
  170. LI r18, r0, uxCriticalNesting
  171. SI r18, r1, portCRITICAL_NESTING_OFFSET
  172. /* Stack MSR. */
  173. mfs r18, rmsr
  174. SI r18, r1, portMSR_OFFSET
  175. #if( XPAR_MICROBLAZE_USE_FPU != 0 )
  176. /* Stack FSR. */
  177. mfs r18, rfsr
  178. SI r18, r1, portFSR_OFFSET
  179. #endif
  180. #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
  181. /* Save the stack limits */
  182. mfs r18, rslr
  183. swi r18, r1, portSLR_OFFSET
  184. mfs r18, rshr
  185. swi r18, r1, portSHR_OFFSET
  186. #endif
  187. /* Save the top of stack value to the TCB. */
  188. LI r3, r0, pxCurrentTCB
  189. STORE r1, r0, r3
  190. .endm
  191. .macro portRESTORE_CONTEXT
  192. /* Load the top of stack value from the TCB. */
  193. LI r18, r0, pxCurrentTCB
  194. LOAD r1, r0, r18
  195. #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
  196. /* Restore the stack limits -- must not load from r1 (Stack Pointer)
  197. because if the address of load or store instruction is out of range,
  198. it will trigger Stack Protection Violation exception. */
  199. or r18, r0, r1
  200. lwi r12, r18, portSLR_OFFSET
  201. mts rslr, r12
  202. lwi r12, r18, portSHR_OFFSET
  203. mts rshr, r12
  204. #endif
  205. /* Restore the general registers. */
  206. LI r31, r1, portR31_OFFSET
  207. LI r30, r1, portR30_OFFSET
  208. LI r29, r1, portR29_OFFSET
  209. LI r28, r1, portR28_OFFSET
  210. LI r27, r1, portR27_OFFSET
  211. LI r26, r1, portR26_OFFSET
  212. LI r25, r1, portR25_OFFSET
  213. LI r24, r1, portR24_OFFSET
  214. LI r23, r1, portR23_OFFSET
  215. LI r22, r1, portR22_OFFSET
  216. LI r21, r1, portR21_OFFSET
  217. LI r20, r1, portR20_OFFSET
  218. LI r19, r1, portR19_OFFSET
  219. LI r17, r1, portR17_OFFSET
  220. LI r16, r1, portR16_OFFSET
  221. LI r15, r1, portR15_OFFSET
  222. LI r14, r1, portR14_OFFSET
  223. LI r13, r1, portR13_OFFSET
  224. LI r12, r1, portR12_OFFSET
  225. LI r11, r1, portR11_OFFSET
  226. LI r10, r1, portR10_OFFSET
  227. LI r9, r1, portR9_OFFSET
  228. LI r8, r1, portR8_OFFSET
  229. LI r7, r1, portR7_OFFSET
  230. LI r6, r1, portR6_OFFSET
  231. LI r5, r1, portR5_OFFSET
  232. LI r4, r1, portR4_OFFSET
  233. LI r3, r1, portR3_OFFSET
  234. LI r2, r1, portR2_OFFSET
  235. /* Reload the rmsr from the stack. */
  236. LI r18, r1, portMSR_OFFSET
  237. mts rmsr, r18
  238. #if( XPAR_MICROBLAZE_USE_FPU != 0 )
  239. /* Reload the FSR from the stack. */
  240. LI r18, r1, portFSR_OFFSET
  241. mts rfsr, r18
  242. #endif
  243. /* Load the critical nesting value. */
  244. LI r18, r1, portCRITICAL_NESTING_OFFSET
  245. SI r18, r0, uxCriticalNesting
  246. /* Test the critical nesting value. If it is non zero then the task last
  247. exited the running state using a yield. If it is zero, then the task
  248. last exited the running state through an interrupt. */
  249. XORI r18, r18, 0
  250. BNEI r18, exit_from_yield
  251. /* r18 was being used as a temporary. Now restore its true value from the
  252. stack. */
  253. LI r18, r1, portR18_OFFSET
  254. /* Remove the stack frame. */
  255. ADDLIK r1, r1, portCONTEXT_SIZE
  256. /* Return using rtid so interrupts are re-enabled as this function is
  257. exited. */
  258. rtid r14, 0
  259. OR r0, r0, r0
  260. .endm
  261. /* This function is used to exit portRESTORE_CONTEXT() if the task being
  262. returned to last left the Running state by calling taskYIELD() (rather than
  263. being preempted by an interrupt). */
  264. .text
  265. #ifdef __arch64__
  266. .align 8
  267. #else
  268. .align 4
  269. #endif
  270. exit_from_yield:
  271. /* r18 was being used as a temporary. Now restore its true value from the
  272. stack. */
  273. LI r18, r1, portR18_OFFSET
  274. /* Remove the stack frame. */
  275. ADDLIK r1, r1, portCONTEXT_SIZE
  276. /* Return to the task. */
  277. rtsd r14, 0
  278. OR r0, r0, r0
  279. .text
  280. #ifdef __arch64__
  281. .align 8
  282. #else
  283. .align 4
  284. #endif
  285. _interrupt_handler:
  286. portSAVE_CONTEXT
  287. /* Stack the return address. */
  288. SI r14, r1, portR14_OFFSET
  289. /* Switch to the ISR stack. */
  290. LI r1, r0, pulISRStack
  291. #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
  292. ori r18, r0, _stack_end
  293. mts rslr, r18
  294. ori r18, r0, _stack
  295. mts rshr, r18
  296. #endif
  297. /* The parameter to the interrupt handler. */
  298. ORI r5, r0, configINTERRUPT_CONTROLLER_TO_USE
  299. /* Execute any pending interrupts. */
  300. BRALID r15, XIntc_DeviceInterruptHandler
  301. OR r0, r0, r0
  302. /* See if a new task should be selected to execute. */
  303. LI r18, r0, ulTaskSwitchRequested
  304. OR r18, r18, r0
  305. /* If ulTaskSwitchRequested is already zero, then jump straight to
  306. restoring the task that is already in the Running state. */
  307. BEQI r18, task_switch_not_requested
  308. /* Set ulTaskSwitchRequested back to zero as a task switch is about to be
  309. performed. */
  310. SI r0, r0, ulTaskSwitchRequested
  311. /* ulTaskSwitchRequested was not 0 when tested. Select the next task to
  312. execute. */
  313. BRALID r15, vTaskSwitchContext
  314. OR r0, r0, r0
  315. task_switch_not_requested:
  316. /* Restore the context of the next task scheduled to execute. */
  317. portRESTORE_CONTEXT
  318. .text
  319. #ifdef __arch64__
  320. .align 8
  321. #else
  322. .align 4
  323. #endif
  324. VPortYieldASM:
  325. portSAVE_CONTEXT
  326. /* Modify the return address so a return is done to the instruction after
  327. the call to VPortYieldASM. */
  328. ADDI r14, r14, 8
  329. SI r14, r1, portR14_OFFSET
  330. /* Switch to use the ISR stack. */
  331. LI r1, r0, pulISRStack
  332. #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
  333. ori r18, r0, _stack_end
  334. mts rslr, r18
  335. ori r18, r0, _stack
  336. mts rshr, r18
  337. #endif
  338. /* Select the next task to execute. */
  339. BRALID r15, vTaskSwitchContext
  340. OR r0, r0, r0
  341. /* Restore the context of the next task scheduled to execute. */
  342. portRESTORE_CONTEXT
  343. .text
  344. #ifdef __arch64__
  345. .align 8
  346. #else
  347. .align 4
  348. #endif
  349. vPortStartFirstTask:
  350. portRESTORE_CONTEXT
  351. #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
  352. .text
  353. #ifdef __arch64__
  354. .align 8
  355. #else
  356. .align 4
  357. #endif
  358. vPortExceptionHandlerEntry:
  359. /* Take a copy of the stack pointer before vPortExecptionHandler is called,
  360. storing its value prior to the function stack frame being created. */
  361. SI r1, r0, pulStackPointerOnFunctionEntry
  362. BRALID r15, vPortExceptionHandler
  363. OR r0, r0, r0
  364. #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */