/*
.section .text.entry
.align 8
.extern switchTask
.extern getCurrentTaskStackTopAddr
.global prvPortStartFirstTask
/**
/**
or exception
/
/ Save caller registers /
.macro SAVE_CONTEXT
csrrw sp, CSR_MSCRATCHCSWL, sp
/ Allocate stack space for context saving */
addi sp, sp, -20*REGBYTES
addi sp, sp, -14*REGBYTES
STORE x1, 0REGBYTES(sp)
STORE x4, 1REGBYTES(sp)
STORE x5, 2REGBYTES(sp)
STORE x6, 3REGBYTES(sp)
STORE x7, 4REGBYTES(sp)
STORE x10, 5REGBYTES(sp)
STORE x11, 6REGBYTES(sp)
STORE x12, 7REGBYTES(sp)
STORE x13, 8REGBYTES(sp)
STORE x14, 9REGBYTES(sp)
STORE x15, 10*REGBYTES(sp)
STORE x16, 14REGBYTES(sp)
STORE x17, 15REGBYTES(sp)
STORE x28, 16REGBYTES(sp)
STORE x29, 17REGBYTES(sp)
STORE x30, 18REGBYTES(sp)
STORE x31, 19REGBYTES(sp)
.endm
/**
from interrupt or exeception
/
/ Restore caller registers /
.macro RESTORE_CONTEXT
LOAD x1, 0REGBYTES(sp)
LOAD x4, 1REGBYTES(sp)
LOAD x5, 2REGBYTES(sp)
LOAD x6, 3REGBYTES(sp)
LOAD x7, 4REGBYTES(sp)
LOAD x10, 5REGBYTES(sp)
LOAD x11, 6REGBYTES(sp)
LOAD x12, 7REGBYTES(sp)
LOAD x13, 8REGBYTES(sp)
LOAD x14, 9REGBYTES(sp)
LOAD x15, 10REGBYTES(sp)
LOAD x16, 14REGBYTES(sp)
LOAD x17, 15REGBYTES(sp)
LOAD x28, 16REGBYTES(sp)
LOAD x29, 17REGBYTES(sp)
LOAD x30, 18REGBYTES(sp)
LOAD x31, 19REGBYTES(sp)
/ De-allocate the stack space /
addi sp, sp, 20*REGBYTES
/ De-allocate the stack space /
addi sp, sp, 14*REGBYTES
csrrw sp, CSR_MSCRATCHCSWL, sp
.endm
/**
/**
/**
to be saved before enter interrupt handler and be restored before return.
/
.section .text.trap
/ In CLIC mode, the exeception entry must be 64bytes aligned /
.align 6
.global exc_entry
exc_entry:
/ Save the caller saving registers (context) /
SAVE_CONTEXT
/ Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/*
system_Device.c, you can adjust it as you want
*/
call core_exception_handler
/ Restore the necessary CSR registers /
RESTORE_CSR_CONTEXT
/ Restore the caller saving registers (context) /
RESTORE_CONTEXT
/ Return to regular code /
mret
/**
to be saved before enter interrupt handler and be restored before return.
/
.section .text.irq
/ In CLIC mode, the interrupt entry must be 4bytes aligned /
.align 2
.global irq_entry
/ This label will be set to MTVT2 register /
irq_entry:
/ Save the caller saving registers (context) /
SAVE_CONTEXT
/ Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/* This special CSR read/write operation, which is actually
jump to its vector-entry-label, and update the link register
*/
csrrw ra, CSR_JALMNXTI, ra
/ Critical section with interrupts disabled /
DISABLE_MIE
/ Restore the necessary CSR registers /
RESTORE_CSR_CONTEXT
/ Restore the caller saving registers (context) /
RESTORE_CONTEXT
/ Return to regular code /
mret
/ Default Handler for Exceptions / Interrupts /
.global default_intexc_handler
Undef_Handler:
default_intexc_handler:
1:
j 1b
/ Start the first task. This also clears the bit that indicates the FPU is
in use in case the FPU was used before the scheduler was started - which
would otherwise result in the unnecessary leaving of space in the stack
for lazy saving of FPU registers. /
.align 3
prvPortStartFirstTask: // 开始第一个任务
/ Setup Interrupt Stack using
The stack that was used by main()
before the scheduler is started is
no longer required after the scheduler is started.
Interrupt stack pointer is stored in CSR_MSCRATCH /
la t0, _sp
csrw CSR_MSCRATCH, t0 // 暂存寄存器
LOAD sp, getCurrentTaskStackTopAddr / Load pxCurrentTCB. /
LOAD sp, 0x0(sp) / Read sp from first TCB member /
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp) // 异常结束后返回到这个地址
csrw CSR_MEPC, t0 // 异常PC寄存器
/* Pop mstatus from stack and set it */
LOAD t0, (portRegNum - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0 // 异常处理状态寄存器
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
addi sp, sp, portCONTEXT_SIZE
mret // 中断处理结束必须使用mret从NMI服务程序中退出,并返回主程序
// 下条指令从mpec寄存器中读取
.align 2
.global eclic_msip_handler
eclic_msip_handler: // TIMER生成软件中断 1产生软件中断 0取消软件中断 由MSIP寄存器管理
addi sp, sp, -portCONTEXT_SIZE
STORE x1, 1 REGBYTES(sp) / RA / // 保存内容
STORE x5, 2 REGBYTES(sp)
STORE x6, 3 REGBYTES(sp)
STORE x7, 4 REGBYTES(sp)
STORE x8, 5 REGBYTES(sp)
STORE x9, 6 REGBYTES(sp)
STORE x10, 7 REGBYTES(sp)
STORE x11, 8 REGBYTES(sp)
STORE x12, 9 REGBYTES(sp)
STORE x13, 10 REGBYTES(sp)
STORE x14, 11 REGBYTES(sp)
STORE x15, 12 REGBYTES(sp)
STORE x16, 13 * REGBYTES(sp)
STORE x17, 14 * REGBYTES(sp)
STORE x18, 15 * REGBYTES(sp)
STORE x19, 16 * REGBYTES(sp)
STORE x20, 17 * REGBYTES(sp)
STORE x21, 18 * REGBYTES(sp)
STORE x22, 19 * REGBYTES(sp)
STORE x23, 20 * REGBYTES(sp)
STORE x24, 21 * REGBYTES(sp)
STORE x25, 22 * REGBYTES(sp)
STORE x26, 23 * REGBYTES(sp)
STORE x27, 24 * REGBYTES(sp)
STORE x28, 25 * REGBYTES(sp)
STORE x29, 26 * REGBYTES(sp)
STORE x30, 27 * REGBYTES(sp)
STORE x31, 28 * REGBYTES(sp)
/* Push mstatus to stack */
csrr t0, CSR_MSTATUS
STORE t0, (portRegNum - 1) * REGBYTES(sp)
/* Push additional registers */
/* Store sp to task stack */
LOAD t0, getCurrentTaskStackTopAddr
STORE sp, 0(t0)
csrr t0, CSR_MEPC
STORE t0, 0(sp)
jal switchTask
/* Switch task context */
LOAD t0, getCurrentTaskStackTopAddr /* Load pxCurrentTCB. */
LOAD sp, 0x0(t0) /* Read sp from first TCB member */
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp)
csrw CSR_MEPC, t0
/* Pop additional registers */
/* Pop mstatus from stack and set it */
LOAD t0, (portRegNum - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
addi sp, sp, portCONTEXT_SIZE
mret