1/* 2 * Copyright (c) 2021 KT-Elektronik, Klaucke und Partner GmbH 3 * Copyright (c) 2024 Renesas Electronics Corporation 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#include <zephyr/toolchain.h> 8#include <zephyr/linker/sections.h> 9#include <offsets_short.h> 10 11GTEXT(_z_rx_arch_switch) 12GTEXT(_switch_isr_wrapper) 13 14/* void z_rx_arch_switch(void *switch_to, void **switched_from) 15 * 16 * @brief switch between threads 17 * 18 * @param switch_to (r1) pointer to switch handle of the new thread 19 * @param switched_from (r2) pointer to pointer to switch handle of the old 20 * thread 21 * 22 * Thread-switching is treated differently depending on whether it is a 23 * cooperative switch triggered by old thread itself or a preemptive switch 24 * triggered by an interrupt (in this case the function has been called from an 25 * ISR). 26 */ 27.section .text._z_rx_arch_switch 28.align 4 29_z_rx_arch_switch: 30 31 mvfc psw,r3 32 tst #0x130000, r3 /* test if PM, U or I bit are set*/ 33 bz _z_rx_context_switch_isr /* if none of them are set, this is an isr */ 34 35 mov #_coop_switch_to,r3 36 mov r1,[r3] 37 mov #_coop_switched_from,r3 38 mov r2,[r3] 39 40 /* trigger unconditional interrupt dedicated to thread switching. The content of r1 and r2 41 * will not change by invoking the interrupt so the parameters switch_to and switched_from 42 * will be available in _z_rx_context_switch_isr, which has been entered into the vector 43 * table as ISR for interrupt 1 44 */ 45 int #1 46 47 /* at this point, r0 points to the entry point, so RTS will enter it */ 48 rts 49 50/* void switch_isr_wrapper(void) 51 * 52 * @brief isr for interrupt 1 as wrapper for _z_rx_context_switch_isr 53 * 54 * _z_rx_context_switch_isr ends in rts, so it does not return from the interrupt context 55 */ 56.section .text._switch_isr_wrapper 57.align 4 58_switch_isr_wrapper: 59 pushm r1-r15 60 61 /* Save the accumulator. */ 62 mvfachi r15 /* Accumulator high 32 bits. */ 63 push r15 64 mvfacmi r15 /* Accumulator middle 32 bits. */ 65 shll #16, r15 /* Shifted left as it is restored to the low order word.*/ 66 push r15 67 68 mov #_coop_switch_to,r3 69 mov [r3],r1 70 mov #_coop_switched_from,r3 71 mov [r3],r2 72 73 bsr _z_rx_context_switch_isr 74 75 /* Restore the registers from the stack of the task pointed to by 76 pxCurrentTCB. */ 77 pop r15 78 mvtaclo r15 /* Accumulator low 32 bits. */ 79 pop r15 80 mvtachi r15 /* Accumulator high 32 bits. */ 81 82 popm r1-r15 83 rte 84 85/* void z_rx_context_switch_isr(void *switch_to, void **switched_from) 86 * 87 * @brief switch between threads in the interrupt context 88 * 89 * @param switch_to (r1) pointer to switch handle of the new thread 90 * @param switched_from (r2) pointer to pointer to switch handle of the old thread 91 * 92 * since this is part of an ISR, PSW, PC and general registers of the old thread are already 93 * stored in the interrupt stack, so copy the corresponding part of the interrupt stack to the 94 * stack of the interrupted thread 95 */ 96_z_rx_context_switch_isr: 97 98 /* store arguments switch_to and switched_from to registers r4 and r5 as 99 * registers r2 and r3 are needed for the smovf operation */ 100 mov r1,r4 101 mov r2,r5 102 103 /* set r2 (smovb source address) to the beginning of the interrupt stack */ 104 mov #(_z_interrupt_stacks + CONFIG_ISR_STACK_SIZE)-1,r2 105 106 mvfc usp,r1 /* set r1 (smovb dest) to USP */ 107 108 sub #1,r1 /* correct by one byte to use smovb compared to push/pop */ 109 110 /* set r3 to number of bytes to move 111 * Accumulator 64bit (4byte * 2) 112 * 15*4 byte for 15 general registers 113 * + PSW (4 byte) 114 * + PC (4 byte) 115 */ 116 mov #76,r3 117 smovb /* block copy from interrupt stack to old thread stack */ 118 119 add #1,r1 /* smovb leaves r1 pointing 1 byte before the stack */ 120 add #1,r2 /* same with r2 */ 121 122 mov r1,[r5] /* store stack pointer of old thread in *switched_from */ 123 124 mov r2,r1 /* set r1 (smovf dest) to the beginning of the interrupt stack */ 125 126 mov r4,r2 /* set r2 (smovf source) to the sp of the new thread*/ 127 mov #76,r3 /* set r3 to number of bytes to move */ 128 129 smovf /* block copy from new thread stack to interrupt stack */ 130 131 mvtc r2,usp /* set USP to the new thread stack */ 132 133#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING 134 bsr _z_thread_mark_switched_in 135#endif 136 137 rts 138