1// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15    .global uxInterruptNesting
16    .global uxSchedulerRunning
17    .global xIsrStackTop
18    .global pxCurrentTCB
19    .global vTaskSwitchContext
20    .global xPortSwitchFlag
21
22    .section .text
23
24/**
25 * This function makes the RTOS aware about a ISR entering, it takes the
26 * current task stack saved, places into the TCB, loads the ISR stack
27 * the interrupted stack must be passed in a0. It needs to receive the
28 * ISR nesting code improvements
29 */
30
31    .global rtos_int_enter
32    .type rtos_int_enter, @function
33rtos_int_enter:
34    /* preserve the return address */
35    mv t1, ra
36    mv t2, a0
37
38    /* scheduler not enabled, jump directly to ISR handler */
39    lw t0, uxSchedulerRunning
40    beq t0,zero, rtos_enter_end
41
42    /* increments the ISR nesting count */
43	la t3, uxInterruptNesting
44	lw t4, 0x0(t3)
45	addi t5,t4,1
46	sw  t5, 0x0(t3)
47
48    /* If reached here from another low-prio ISR, skip stack pushing to TCB */
49	bne t4,zero, rtos_enter_end
50
51    /* Save current TCB and load the ISR stack */
52    lw  t0, pxCurrentTCB
53    sw 	t2, 0x0(t0)
54    lw  sp, xIsrStackTop
55
56rtos_enter_end:
57    mv  ra, t1
58    ret
59
60/**
61 * Recovers the next task to run stack pointer and place it into
62 * a0, then the interrupt handler can restore the context of
63 * the next task
64 */
65    .global rtos_int_exit
66    .type rtos_int_exit, @function
67rtos_int_exit:
68    /* may skip RTOS aware interrupt since scheduler was not started */
69    lw t0, uxSchedulerRunning
70    beq t0,zero, rtos_exit_end
71
72    /* update nesting interrupts counter */
73    la t2, uxInterruptNesting
74    lw t3, 0x0(t2)
75
76    /* Already zero, protect against underflow */
77    beq t3, zero, isr_skip_decrement
78    addi t3,t3, -1
79    sw  t3, 0x0(t2)
80
81isr_skip_decrement:
82
83    /* may still have interrupts pending, skip section below and exit */
84    bne t3,zero,rtos_exit_end
85
86    /* Schedule the next task if a yield is pending */
87    la t0, xPortSwitchFlag
88    lw t2, 0x0(t0)
89    beq t2, zero, no_switch
90
91    /* preserve return address and schedule next task
92       stack pointer for riscv should always be 16 byte aligned */
93    addi sp,sp,-16
94    sw  ra, 0(sp)
95    call vTaskSwitchContext
96    lw  ra, 0(sp)
97    addi sp, sp, 16
98
99    /* Clears the switch pending flag */
100    la t0, xPortSwitchFlag
101    mv t2, zero
102    sw  t2, 0x0(t0)
103
104no_switch:
105    /* Recover the stack of next task and prepare to exit : */
106    lw a0, pxCurrentTCB
107    lw a0, 0x0(a0)
108
109rtos_exit_end:
110    ret
111