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