port_asm.S 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * FreeRTOS Kernel V10.4.6
  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. #include <xc.h>
  29. #include <sys/asm.h>
  30. #include "ISR_Support.h"
  31. .set nomips16
  32. .set noreorder
  33. .extern pxCurrentTCB
  34. .extern vTaskSwitchContext
  35. .extern vPortIncrementTick
  36. .extern xISRStackTop
  37. .global vPortStartFirstTask
  38. .global vPortYieldISR
  39. .global vPortTickInterruptHandler
  40. /******************************************************************/
  41. .set noreorder
  42. .set noat
  43. .ent vPortTickInterruptHandler
  44. vPortTickInterruptHandler:
  45. portSAVE_CONTEXT
  46. jal vPortIncrementTick
  47. nop
  48. portRESTORE_CONTEXT
  49. .end vPortTickInterruptHandler
  50. /******************************************************************/
  51. .set noreorder
  52. .set noat
  53. .ent vPortStartFirstTask
  54. vPortStartFirstTask:
  55. /* Simply restore the context of the highest priority task that has been
  56. created so far. */
  57. portRESTORE_CONTEXT
  58. .end vPortStartFirstTask
  59. /*******************************************************************/
  60. .set noreorder
  61. .set noat
  62. .ent vPortYieldISR
  63. vPortYieldISR:
  64. /* Make room for the context. First save the current status so it can be
  65. manipulated. */
  66. addiu sp, sp, -portCONTEXT_SIZE
  67. mfc0 k1, _CP0_STATUS
  68. /* Also save s6 and s5 so they can be used. Any nesting interrupts should
  69. maintain the values of these registers across the ISR. */
  70. sw s6, 44(sp)
  71. sw s5, 40(sp)
  72. sw k1, portSTATUS_STACK_LOCATION(sp)
  73. /* Prepare to re-enabled interrupt above the kernel priority. */
  74. ins k1, zero, 10, 6
  75. ori k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
  76. ins k1, zero, 1, 4
  77. /* s5 is used as the frame pointer. */
  78. add s5, zero, sp
  79. /* Swap to the system stack. This is not conditional on the nesting
  80. count as this interrupt is always the lowest priority and therefore
  81. the nesting is always 0. */
  82. la sp, xISRStackTop
  83. lw sp, (sp)
  84. /* Set the nesting count. */
  85. la k0, uxInterruptNesting
  86. addiu s6, zero, 1
  87. sw s6, 0(k0)
  88. /* s6 holds the EPC value, this is saved with the rest of the context
  89. after interrupts are enabled. */
  90. mfc0 s6, _CP0_EPC
  91. /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
  92. mtc0 k1, _CP0_STATUS
  93. /* Save the context into the space just created. s6 is saved again
  94. here as it now contains the EPC value. */
  95. sw ra, 120(s5)
  96. sw s8, 116(s5)
  97. sw t9, 112(s5)
  98. sw t8, 108(s5)
  99. sw t7, 104(s5)
  100. sw t6, 100(s5)
  101. sw t5, 96(s5)
  102. sw t4, 92(s5)
  103. sw t3, 88(s5)
  104. sw t2, 84(s5)
  105. sw t1, 80(s5)
  106. sw t0, 76(s5)
  107. sw a3, 72(s5)
  108. sw a2, 68(s5)
  109. sw a1, 64(s5)
  110. sw a0, 60(s5)
  111. sw v1, 56(s5)
  112. sw v0, 52(s5)
  113. sw s7, 48(s5)
  114. sw s6, portEPC_STACK_LOCATION(s5)
  115. /* s5 and s6 has already been saved. */
  116. sw s4, 36(s5)
  117. sw s3, 32(s5)
  118. sw s2, 28(s5)
  119. sw s1, 24(s5)
  120. sw s0, 20(s5)
  121. sw $1, 16(s5)
  122. /* s7 is used as a scratch register as this should always be saved across
  123. nesting interrupts. */
  124. mfhi s7
  125. sw s7, 12(s5)
  126. mflo s7
  127. sw s7, 8(s5)
  128. /* Save the stack pointer to the task. */
  129. la s7, pxCurrentTCB
  130. lw s7, (s7)
  131. sw s5, (s7)
  132. /* Set the interrupt mask to the max priority that can use the API. The
  133. yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which
  134. is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever
  135. raise the IPL value and never lower it. */
  136. di
  137. ehb
  138. mfc0 s7, _CP0_STATUS
  139. ins s7, zero, 10, 6
  140. ori s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
  141. /* This mtc0 re-enables interrupts, but only above
  142. configMAX_SYSCALL_INTERRUPT_PRIORITY. */
  143. mtc0 s6, _CP0_STATUS
  144. ehb
  145. /* Clear the software interrupt in the core. */
  146. mfc0 s6, _CP0_CAUSE
  147. ins s6, zero, 8, 1
  148. mtc0 s6, _CP0_CAUSE
  149. ehb
  150. /* Clear the interrupt in the interrupt controller. */
  151. la s6, IFS0CLR
  152. addiu s4, zero, 2
  153. sw s4, (s6)
  154. jal vTaskSwitchContext
  155. nop
  156. /* Clear the interrupt mask again. The saved status value is still in s7. */
  157. mtc0 s7, _CP0_STATUS
  158. ehb
  159. /* Restore the stack pointer from the TCB. */
  160. la s0, pxCurrentTCB
  161. lw s0, (s0)
  162. lw s5, (s0)
  163. /* Restore the rest of the context. */
  164. lw s0, 8(s5)
  165. mtlo s0
  166. lw s0, 12(s5)
  167. mthi s0
  168. lw $1, 16(s5)
  169. lw s0, 20(s5)
  170. lw s1, 24(s5)
  171. lw s2, 28(s5)
  172. lw s3, 32(s5)
  173. lw s4, 36(s5)
  174. /* s5 is loaded later. */
  175. lw s6, 44(s5)
  176. lw s7, 48(s5)
  177. lw v0, 52(s5)
  178. lw v1, 56(s5)
  179. lw a0, 60(s5)
  180. lw a1, 64(s5)
  181. lw a2, 68(s5)
  182. lw a3, 72(s5)
  183. lw t0, 76(s5)
  184. lw t1, 80(s5)
  185. lw t2, 84(s5)
  186. lw t3, 88(s5)
  187. lw t4, 92(s5)
  188. lw t5, 96(s5)
  189. lw t6, 100(s5)
  190. lw t7, 104(s5)
  191. lw t8, 108(s5)
  192. lw t9, 112(s5)
  193. lw s8, 116(s5)
  194. lw ra, 120(s5)
  195. /* Protect access to the k registers, and others. */
  196. di
  197. ehb
  198. /* Set nesting back to zero. As the lowest priority interrupt this
  199. interrupt cannot have nested. */
  200. la k0, uxInterruptNesting
  201. sw zero, 0(k0)
  202. /* Switch back to use the real stack pointer. */
  203. add sp, zero, s5
  204. /* Restore the real s5 value. */
  205. lw s5, 40(sp)
  206. /* Pop the status and epc values. */
  207. lw k1, portSTATUS_STACK_LOCATION(sp)
  208. lw k0, portEPC_STACK_LOCATION(sp)
  209. /* Remove stack frame. */
  210. addiu sp, sp, portCONTEXT_SIZE
  211. mtc0 k1, _CP0_STATUS
  212. mtc0 k0, _CP0_EPC
  213. ehb
  214. eret
  215. nop
  216. .end vPortYieldISR