1/* 2 * Copyright (c) 2020-2020, Bluetrum Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2020/11/18 greedyhao The first version. 9 */ 10 11#include "ab32vg1.h" 12 13.global rt_interrupt_from_thread 14.global rt_interrupt_to_thread 15.global rt_cur_thread_sp 16.global rt_thread_switch_interrupt_flag 17.global rt_interrupt_nest 18 19/* 20 * rt_base_t rt_hw_interrupt_disable(); 21 * a0 -> return 22 */ 23 .global rt_hw_interrupt_disable 24rt_hw_interrupt_disable: 25 lw a5, PICCON(zero) 26 mv a0, a5 27 andi a5, a5, -2 28 sw a5, PICCON(zero) 29 ret 30 31/* 32 * void rt_hw_interrupt_enable(rt_base_t level); 33 * a0 -> level 34 */ 35 .global rt_hw_interrupt_enable 36rt_hw_interrupt_enable: 37 andi a0, a0, 1 38 beqz a0,enable_int_ret 39 lw a5, PICCON(zero) 40 ori a5, a5, 1 41 sw a5,PICCON(zero) 42enable_int_ret: 43 ret 44 45/* Macro for saving task context */ 46.macro save_context 47 addi sp, sp, -124 48 49 /* Save Context */ 50 sw x1, 0(sp) 51 sw x4, 4(sp) 52 sw x5, 8(sp) 53 sw x6, 12(sp) 54 sw x7, 16(sp) 55 sw x8, 20(sp) 56 sw x9, 24(sp) 57 sw x10, 28(sp) 58 sw x11, 32(sp) 59 sw x12, 36(sp) 60 sw x13, 40(sp) 61 sw x14, 44(sp) 62 sw x15, 48(sp) 63 sw x16, 52(sp) 64 sw x17, 56(sp) 65 sw x18, 60(sp) 66 sw x19, 64(sp) 67 sw x20, 68(sp) 68 sw x21, 72(sp) 69 sw x22, 76(sp) 70 sw x23, 80(sp) 71 sw x24, 84(sp) 72 sw x25, 88(sp) 73 sw x26, 92(sp) 74 sw x27, 96(sp) 75 sw x28, 100(sp) 76 sw x29, 104(sp) 77 sw x30, 108(sp) 78 sw x31, 112(sp) 79 80 lw a5, EPC(zero) //Saves current program counter (EPC) as task program counter 81 sw a5, 116(sp) 82 lw a5, EPICCON(zero) 83 sw a5, 120(sp) 84 85 sw sp, rt_cur_thread_sp, a4 //store sp in preempted tasks tcb 86 .endm 87 88 89/* Macro for restoring task context */ 90.macro restore_context 91 92 la a5, rt_cur_thread_sp 93 lw sp, 0(a5) //get new task stack pointer 94 95 /* Load task program counter EPC*/ 96 lw a5, 116(sp) 97 sw a5, EPC(zero) 98 lw a5, 120(sp) 99 sw a5, EPICCON(zero) 100 101 /* Restore registers, 102 Skip global pointer because that does not change */ 103 lw x1, 0(sp) 104 lw x4, 4(sp) 105 lw x5, 8(sp) 106 lw x6, 12(sp) 107 lw x7, 16(sp) 108 lw x8, 20(sp) 109 lw x9, 24(sp) 110 lw x10, 28(sp) 111 lw x11, 32(sp) 112 lw x12, 36(sp) 113 lw x13, 40(sp) 114 lw x14, 44(sp) 115 lw x15, 48(sp) 116 lw x16, 52(sp) 117 lw x17, 56(sp) 118 lw x18, 60(sp) 119 lw x19, 64(sp) 120 lw x20, 68(sp) 121 lw x21, 72(sp) 122 lw x22, 76(sp) 123 lw x23, 80(sp) 124 lw x24, 84(sp) 125 lw x25, 88(sp) 126 lw x26, 92(sp) 127 lw x27, 96(sp) 128 lw x28, 100(sp) 129 lw x29, 104(sp) 130 lw x30, 108(sp) 131 lw x31, 112(sp) 132 133 addi sp, sp, 124 134 mret 135 .endm 136 137/* 138 * void rt_hw_context_switch_to(rt_uint32 to); 139 * r0 --> to 140 */ 141 .globl rt_hw_context_switch_to 142rt_hw_context_switch_to: 143 sw zero, rt_interrupt_from_thread, a4 /*set from thread to 0*/ 144 sw a0, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/ 145 146 sb zero, rt_interrupt_nest, a4 /*rt_interrupt_nest = 0*/ 147 148 li a5, 1 149 sw a5, rt_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_flag = 1; 150 151 SWINT /*kick soft interrupt*/ 152 lw a5, PICCON(zero) /*enable interrupt*/ 153 ori a5, a5, 1 154 sw a5, PICCON(zero) 155 ret 156 157/* 158 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 159 * a0 --> from 160 * a1 --> to 161 */ 162 .globl rt_hw_context_switch 163rt_hw_context_switch: 164 sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/ 165 sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/ 166 li a5, 1 167 sw a5, rt_thread_switch_interrupt_flag, a4 /*rt_thread_switch_interrupt_flag = 1*/ 168 SWINT /*kick soft interrupt*/ 169 ret 170 171 /* 172 * void rt_switch_to_thread(void); 173 * r0 --> to 174 */ 175 .globl rt_switch_to_thread 176rt_switch_to_thread: 177 lw a0, rt_interrupt_from_thread 178 lw a5, rt_cur_thread_sp 179 sw a5, 0(a0) 180 181 lw a0, rt_interrupt_to_thread 182 lw a5, 0(a0) 183 sw a5, rt_cur_thread_sp, a4 184 ret 185 186/* 187 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); 188 * a0 --> from 189 * a1 --> to 190 */ 191 .global rt_hw_context_switch_interrupt 192rt_hw_context_switch_interrupt: 193 lw a5, rt_thread_switch_interrupt_flag 194 bnez a5, _reswitch 195 li a5, 0x01 196 sw a5, rt_thread_switch_interrupt_flag, a4 197 sw a0, rt_interrupt_from_thread, a4 /*set rt_interrupt_from_thread*/ 198_reswitch: 199 sw a1, rt_interrupt_to_thread, a4 /*set rt_interrupt_to_thread*/ 200 ret 201 202 //软中断服务 203 .global rt_soft_isr 204rt_soft_isr: 205 li a5, 0x4 // PICPND = BIT(IRQ_SW_VECTOR); 清软中断Pending 206 sw a5, PICPND(zero) 207 ret 208 209 .globl low_prio_irq 210low_prio_irq: 211 save_context 212 213 lw a5, rt_interrupt_nest 214 bnez a5, _low_prio_irq_exit 215 216 lw a5, cpu_irq_comm_hook 217 jalr a5 218 219 lw a5, rt_thread_switch_interrupt_flag 220 beqz a5, _low_prio_irq_exit // if (rt_thread_switch_interrupt_flag) 221 jal rt_switch_to_thread 222 sw zero, rt_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_flag = 0; 223 224 _low_prio_irq_exit: 225 restore_context 226 227