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