context_gcc.S 5.8 KB
Newer Older
1
/*
2
 * Copyright (c) 2020-2020, Bluetrum Development Team
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020/11/18     greedyhao    The first version.
 */

#include "ab32vg1.h"

.global  rt_interrupt_from_thread
.global  rt_interrupt_to_thread
.global  rt_cur_thread_sp
.global  rt_switch_flag
.global  rt_interrupt_nest

/*
 * rt_base_t rt_hw_interrupt_disable();
 * a0 -> return
 */
    .global rt_hw_interrupt_disable
rt_hw_interrupt_disable:
    lw      a5, PICCON(zero)
    mv      a0, a5
    andi    a5, a5, -2
    sw      a5, PICCON(zero)
    ret

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 * a0 -> level
 */
    .global rt_hw_interrupt_enable
rt_hw_interrupt_enable:
    andi    a0, a0, 1
    beqz    a0,enable_int_ret
    lw      a5, PICCON(zero)
    ori     a5, a5, 1
    sw      a5,PICCON(zero)
enable_int_ret:
    ret

/* Macro for saving task context */
.macro save_context
    addi    sp, sp, -120

    /* Save Context */
    sw      x1, 0(sp)
    sw      x4, 4(sp)
    sw      x5, 8(sp)
    sw      x6, 12(sp)
    sw      x7, 16(sp)
    sw      x8, 20(sp)
    sw      x9, 24(sp)
    sw      x10, 28(sp)
    sw      x11, 32(sp)
    sw      x12, 36(sp)
    sw      x13, 40(sp)
    sw      x14, 44(sp)
    sw      x15, 48(sp)
    sw      x16, 52(sp)
    sw      x17, 56(sp)
    sw      x18, 60(sp)
    sw      x19, 64(sp)
    sw      x20, 68(sp)
    sw      x21, 72(sp)
    sw      x22, 76(sp)
    sw      x23, 80(sp)
    sw      x24, 84(sp)
    sw      x25, 88(sp)
    sw      x26, 92(sp)
    sw      x27, 96(sp)
    sw      x28, 100(sp)
    sw      x29, 104(sp)
    sw      x30, 108(sp)
    sw      x31, 112(sp)

    lw      a5, EPC(zero)                  //Saves current program counter (EPC) as task program counter
    sw      a5, 116(sp)

    sw      sp, rt_cur_thread_sp, a4                       //store sp in preempted tasks tcb
    .endm


/* Macro for restoring task context */
.macro restore_context

    la      a5, rt_cur_thread_sp
    lw      sp, 0(a5)                       //get new task stack pointer

    /* Load task program counter  EPC*/
    lw      a5, 116(sp)
    sw      a5, EPC(zero)

    /* Restore registers,
       Skip global pointer because that does not change */
    lw      x1, 0(sp)
    lw      x4, 4(sp)
    lw      x5, 8(sp)
    lw      x6, 12(sp)
    lw      x7, 16(sp)
    lw      x8, 20(sp)
    lw      x9, 24(sp)
    lw      x10, 28(sp)
    lw      x11, 32(sp)
    lw      x12, 36(sp)
    lw      x13, 40(sp)
    lw      x14, 44(sp)
    lw      x15, 48(sp)
    lw      x16, 52(sp)
    lw      x17, 56(sp)
    lw      x18, 60(sp)
    lw      x19, 64(sp)
    lw      x20, 68(sp)
    lw      x21, 72(sp)
    lw      x22, 76(sp)
    lw      x23, 80(sp)
    lw      x24, 84(sp)
    lw      x25, 88(sp)
    lw      x26, 92(sp)
    lw      x27, 96(sp)
    lw      x28, 100(sp)
    lw      x29, 104(sp)
    lw      x30, 108(sp)
    lw      x31, 112(sp)

    addi    sp, sp, 120
    mret
    .endm

/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * r0 --> to
 */
    .globl rt_hw_context_switch_to
rt_hw_context_switch_to:
    sw      zero, rt_interrupt_from_thread, a4                         /*set from thread to 0*/
    sw      a0, rt_interrupt_to_thread, a4                           /*set rt_interrupt_to_thread*/

    sb      zero, rt_interrupt_nest, a4                                /*rt_interrupt_nest = 0*/

    li      a5, 1
    sw      a5, rt_switch_flag, a4                                  // rt_switch_flag = 1;

    SWINT                                                           /*kick soft interrupt*/
    lw      a5, PICCON(zero)                                                 /*enable interrupt*/
    ori     a5, a5, 1
    sw      a5, PICCON(zero)
    ret

/*
 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 * a0 --> from
 * a1 --> to
 */
    .globl rt_hw_context_switch
rt_hw_context_switch:
    sw      a0, rt_interrupt_from_thread, a4                         /*set rt_interrupt_from_thread*/
    sw      a1, rt_interrupt_to_thread, a4                          /*set rt_interrupt_to_thread*/
    li      a5, 1
    sw      a5, rt_switch_flag, a4                                  // rt_switch_flag = 1;
    SWINT                                                           /*kick soft interrupt*/
    ret

 /*
 * void rt_switch_to_thread(void);
 * r0 --> to
 */
    .globl rt_switch_to_thread
rt_switch_to_thread:
    lw     a0, rt_interrupt_from_thread
    lw     a5, rt_cur_thread_sp
    sw     a5, 0(a0)

    lw     a0, rt_interrupt_to_thread
    lw     a5, 0(a0)
    sw     a5, rt_cur_thread_sp, a4
    ret

/*
 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
 * a0 --> from
 * a1 --> to
 */
    .global rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
    lw      a5, rt_switch_flag
    bnez    a5, _reswitch
    li      a5, 0x01
    sw      a5, rt_switch_flag, a4
    sw      a0, rt_interrupt_from_thread, a4                       /*set rt_interrupt_from_thread*/
_reswitch:
    sw      a1, rt_interrupt_to_thread, a4                        /*set rt_interrupt_to_thread*/
    ret

    //软中断服务
    .global rt_soft_isr
rt_soft_isr:
    li      a5, 0x4                                                 // PICPND = BIT(IRQ_SW_VECTOR); 清软中断Pending
    sw      a5, PICPND(zero)
    ret

    .globl low_prio_irq
low_prio_irq:
    save_context
    li      a5, 1
    sb      a5, rt_interrupt_nest, a4                               // rt_interrupt_nest = 1;

    lw      a5, cpu_irq_comm_hook
    jalr    a5

    lw      a5, rt_switch_flag
    beqz    a5, _low_prio_irq_exit                                  // if (rt_switch_flag)
    jal     rt_switch_to_thread
    sw      zero, rt_switch_flag, a4                                // rt_switch_flag = 0;

    _low_prio_irq_exit:
    sb      zero, rt_interrupt_nest, a4                             // rt_interrupt_nest = 0;
    restore_context