1// Copyright (c) 2020, XMOS Ltd, All rights reserved 2 3#include "rtos_support_rtos_config.h" 4 5/* The FreeRTOS interrupt code calls vTaskSwitchContext. 6Therfore it must be added to the rtos_isr group with the 7rest of the ISR callback functions. */ 8.weak _fptrgroup.rtos_isr.nstackwords.group 9.add_to_set _fptrgroup.rtos_isr.nstackwords.group, vTaskSwitchContext.nstackwords, vTaskSwitchContext 10 11.globl kexcept 12.align 128 /* align the kernel section to 128 bytes */ 13.type kexcept,@function 14.issue_mode dual 15.cc_top kexcept.function, kexcept 16kexcept: 17 ldc r11, 0x0008 18 shl r11, r11, 16 19 ldc r9, 0x0080 20 or r11, r11, r9 21 bau r11 //_TrapHandler is at 0x00080080. TODO: Is it always? Why can't I access the symbol _TrapHandler? 22 23_yield: 24 {set sp, r4 /* Restore the task's SP to save the rest of its context. */ 25 get r11, id} /* Get the logical core ID into r11. */ 26 ldaw r0, dp[rtos_core_map] 27 ldw r0, r0[r11] /* Translate to the RTOS core ID into r0 */ 28 bu _yield_continue /* Skip the ulPortYieldRequired check and jump right to */ 29 /* the context save and switch. Also skips saving SPC */ 30 /* since the kcall handler has already saved it. */ 31 32.align 64 33kcall: 34 /* start saving the thread's context */ 35 extsp RTOS_SUPPORT_INTERRUPT_STACK_GROWTH 36 stw r1, sp[9] 37 stw r11, sp[19] 38 39 /* kcall sets SPC to the instruction of the kcall rather than the next instruction */ 40 /* so we need to adjust the SPC value that we save to the stack: */ 41 stw spc, sp[1] /* save the saved program counter onto the stack... */ 42 ldw r1, sp[1] /* so that we can load it into r1 (which we have already saved). */ 43 add r1, r1, 4 /* Add 4 to the spc to make it point to the instruction after the kcall. */ 44 {stw r1, sp[1] /* Now save it to the stack. */ 45 46 /* kcall uses the same common function as interrupt callbacks. */ 47 /* tell it to call _yield above. */ 48 ldap r11, _yield} 49 mov r1, r11 50 51 /* fall into rtos_interrupt_callback_common */ 52 53.globl rtos_interrupt_callback_common 54rtos_interrupt_callback_common: 55 /* This is the body of the RTOS _xcore_c_interrupt_callback_XXX functions. */ 56 /* r1 = interrupt_callback_t function */ 57 58 /* Save the thread's context onto the thread's stack. */ 59 /* The stack was extended for this by the wrapper function. */ 60 /* Begin only by saving some registers. The rest will be saved */ 61 /* later if vTaskSwitchContext() needs to be called. */ 62 /* DP and CP need to be saved because these are restored for the kernel ISR. */ 63 /* LR needs to be saved because it is clobbered when calling the callback. */ 64 /* r0-r3, and r11 need to be saved because the callback may clobber them. */ 65 /* r4 is saved because it is used here to hold the task SP. */ 66 67 stw dp, sp[5] 68 stw cp, sp[6] 69 stw lr, sp[7] 70 stw r0, sp[8] 71/*stw r1, sp[9] already saved by the wrapper function. */ 72 stw r2, sp[10] 73 stw r3, sp[11] 74 {stw r4, sp[12] 75/*stw r11, sp[19] already saved by the wrapper function. */ 76 77 ldaw r4, sp[0]} /* Get value of current stackpointer into r4. */ 78 79 {kentsp 0 /* switch to the kernel stack. */ 80 /* The value 0 is safe to use since we don't need the SP */ 81 /* that it saves to KSP[0]. We already have it in r4. */ 82 83 get r11, ed} /* Get the event data... */ 84 ldw dp, sp[3] /* (Restore CP and DP required for the RTOS ISR */ 85 ldw cp, sp[4] /* in case the active thread has modified them.) */ 86 {mov r0, r11 /* ...into the first argument for the callback function, */ 87 bla r1} /* and call the callback function. */ 88 89 {set sp, r4 /* Restore the task's SP now. */ 90 91 get r11, id} /* Get the logical core ID into r11. */ 92 ldaw r0, dp[rtos_core_map] 93 ldw r0, r0[r11] /* Translate to the RTOS core ID into r0. */ 94 ldaw r2, dp[ulPortYieldRequired] /* Get the yield required array into r2. */ 95 ldw r1, r2[r0] /* Is a yield required for this core? */ 96 {bf r1, _freertos_restore_ctx_partial /* If not, restore the context now. */ 97 ldc r1, 0} 98 stw r1, r2[r0] /* Otherwise, clear the yield required flag. */ 99 100 /* Save the rest of the current task's context. */ 101 102 /* Save standard xs2 regs */ 103 stw spc, sp[1] 104_yield_continue: 105 stw ssr, sp[2] 106 stw sed, sp[3] 107 stw et, sp[4] 108 stw r5, sp[13] 109 stw r6, sp[14] 110 stw r7, sp[15] 111 stw r8, sp[16] 112 stw r9, sp[17] 113 stw r10, sp[18] 114#if 1 115 /* Save VPU status and headroom */ 116 vgetc r11 117 {stw r11, sp[20] 118 /* Save VPU regs */ 119 ldaw r11, sp[21]} 120 {vstr r11[0] 121 ldaw r11, sp[29]} 122 {vstd r11[0] 123 ldaw r11, sp[37]} 124 vstc r11[0] 125#endif 126 ldaw r5, dp[pxCurrentTCBs] /* Get the current TCB array into r5. */ 127 ldw r1, r5[r0] /* Get this core's current TCB pointer into r1. */ 128 stw r4, r1[0x0] /* Save the current task's SP to the first */ 129 /* word (top of stack) in the current TCB. */ 130 131 {kentsp 0 /* switch back to the kernel stack. */ 132 133 mov r6, r0} /* copy the RTOS core ID into r6 so we don't lose it. */ 134 ldap r11, vTaskSwitchContext 135 bla r11 /* Finally call vTaskSwitchContext(core_id) now that the task's */ 136 /* entire context is saved. Note the core id in r0 is the argument. */ 137 138//krestsp 0 /* unnecessary since KSP is already set and the SP */ 139 /* is being restored next from the current TCB. */ 140 141.globl _freertos_restore_ctx 142_freertos_restore_ctx: 143 144 ldw r0, r5[r6] /* get this core's current TCB pointer into r0 */ 145 ldw r0, r0[0x0] /* Get the top of the stack from the current TCB... */ 146 set sp, r0 /* into the stack pointer register. */ 147 148 /* Restore the current task's context */ 149#if 1 150 /* Restore VPU regs */ 151 ldaw r11, sp[37] 152 {vldc r11[0] 153 ldaw r11, sp[29]} 154 {vldd r11[0] 155 ldaw r11, sp[21]} 156 vldr r11[0] 157 /* Restore VPU status and headroom */ 158 ldw r11, sp[20] 159 vsetc r11 160#endif 161 /* Restore standard xs2 regs */ 162 ldw spc, sp[1] 163 ldw ssr, sp[2] 164 ldw sed, sp[3] 165 ldw et, sp[4] 166 ldw r5, sp[13] 167 ldw r6, sp[14] 168 ldw r7, sp[15] 169 ldw r8, sp[16] 170 ldw r9, sp[17] 171 ldw r10, sp[18] 172_freertos_restore_ctx_partial: 173 ldw dp, sp[5] 174 ldw cp, sp[6] 175 ldw lr, sp[7] 176 ldw r0, sp[8] 177 ldw r1, sp[9] 178 ldw r2, sp[10] 179 ldw r3, sp[11] 180 ldw r4, sp[12] 181 {ldw r11, sp[19] 182 183 /* shrink the stack by the size of the context just restored */ 184 ldaw sp, sp[RTOS_SUPPORT_INTERRUPT_STACK_GROWTH]} 185 186 kret /* exit kernel mode and return to the thread */ 187 188.cc_bottom kexcept.function 189 190