227 lines
6.0 KiB
ArmAsm
227 lines
6.0 KiB
ArmAsm
/*
|
|
* Copyright (c) 2020-2020, Bluetrum Development Team
|
|
*
|
|
* 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_thread_switch_interrupt_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, -124
|
|
|
|
/* 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)
|
|
lw a5, EPICCON(zero)
|
|
sw a5, 120(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)
|
|
lw a5, 120(sp)
|
|
sw a5, EPICCON(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, 124
|
|
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_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_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_thread_switch_interrupt_flag, a4 /*rt_thread_switch_interrupt_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_thread_switch_interrupt_flag
|
|
bnez a5, _reswitch
|
|
li a5, 0x01
|
|
sw a5, rt_thread_switch_interrupt_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
|
|
|
|
lw a5, rt_interrupt_nest
|
|
bnez a5, _low_prio_irq_exit
|
|
|
|
lw a5, cpu_irq_comm_hook
|
|
jalr a5
|
|
|
|
lw a5, rt_thread_switch_interrupt_flag
|
|
beqz a5, _low_prio_irq_exit // if (rt_thread_switch_interrupt_flag)
|
|
jal rt_switch_to_thread
|
|
sw zero, rt_thread_switch_interrupt_flag, a4 // rt_thread_switch_interrupt_flag = 0;
|
|
|
|
_low_prio_irq_exit:
|
|
restore_context
|
|
|