Merge pull request #34 from acevest/add_irq_stack

risc-v add irq stack
This commit is contained in:
Supowang1989
2019-10-09 12:14:43 +08:00
committed by GitHub
7 changed files with 79 additions and 115 deletions

View File

@@ -34,7 +34,7 @@
// MPIL 23:16 previous interrupt level // MPIL 23:16 previous interrupt level
// Reserved 15:12 0 // Reserved 15:12 0
// EXCCODE 11:0 exception code // EXCCODE 11:0 exception code
#define SOC_MCAUSE_EXP_MASK 0x00000FFF #define MCAUSE_EXP_CODE_MASK 0x00000FFF
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
void port_cpu_init(); void port_cpu_init();

View File

@@ -7,6 +7,6 @@
irq_entry: irq_entry:
j rv32_exception_entry j rv32_exception_entry
.align 6 .align 2
trap_entry: trap_entry:
j rv32_exception_entry j rv32_exception_entry

View File

@@ -1,6 +1,14 @@
#include <tos.h> #include <tos.h>
#include <riscv_port.h> #include <riscv_port.h>
#ifndef TOS_CFG_IRQ_STK_SIZE
#warning "did not specify the irq stack size, use default value"
#define TOS_CFG_IRQ_STK_SIZE 128
#endif
k_stack_t k_irq_stk[TOS_CFG_IRQ_STK_SIZE];
k_stack_t *k_irq_stk_top = k_irq_stk + TOS_CFG_IRQ_STK_SIZE;
__KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick) __KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
{ {
port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO); port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO);
@@ -8,7 +16,14 @@ __KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
} }
__KERNEL__ void cpu_init(void) { __KERNEL__ void cpu_init(void) {
// reserve storage space for sp registers
k_irq_stk_top = (k_stack_t *)(((cpu_addr_t) k_irq_stk_top) - sizeof(cpu_data_t));
k_irq_stk_top = (k_stack_t *)(((cpu_addr_t) k_irq_stk_top) & 0xFFFFFFFC);
k_cpu_cycle_per_tick = TOS_CFG_CPU_CLOCK / k_cpu_tick_per_second; k_cpu_cycle_per_tick = TOS_CFG_CPU_CLOCK / k_cpu_tick_per_second;
cpu_systick_init(k_cpu_cycle_per_tick); cpu_systick_init(k_cpu_cycle_per_tick);
port_cpu_init(); port_cpu_init();
@@ -88,27 +103,26 @@ __KERNEL__ k_stack_t *cpu_task_stk_init(void *entry,
cpu_context_t *regs = 0; cpu_context_t *regs = 0;
sp = (cpu_data_t *)&stk_base[stk_size]; sp = (cpu_data_t *)&stk_base[stk_size];
sp = (cpu_data_t *)((cpu_addr_t)(sp) & 0xFFFFFFF8); sp = (cpu_data_t *)((cpu_addr_t)(sp) & 0xFFFFFFFC);
sp -= (sizeof(cpu_context_t)/sizeof(cpu_data_t)); sp -= (sizeof(cpu_context_t)/sizeof(cpu_data_t));
regs = (cpu_context_t*) sp; regs = (cpu_context_t*) sp;
for(int i=0; i<(sizeof(cpu_context_t)/sizeof(cpu_data_t)); i++) { for(int i=1; i<(sizeof(cpu_context_t)/sizeof(cpu_data_t)); i+=2) {
#define _V(v) ((unsigned int)((v/10) << 4 | (v % 10))) // every task begin with "Tencent"
*(sp + i) = (_V(i) << 24) | (_V(i) << 16) | (_V(i) << 8) | _V(i); *(sp + i - 1) = 0x0054656E;
#undef _V *(sp + i - 0) = 0x63656E74;
} }
cpu_data_t gp = 0; cpu_data_t gp = 0;
__ASM__ __VOLATILE__ ("mv %0, gp":"=r"(gp)); __ASM__ __VOLATILE__ ("mv %0, gp":"=r"(gp));
regs->gp = (cpu_data_t)gp; // gp: global pointer regs->gp = (cpu_data_t)gp; // global pointer
regs->a0 = (cpu_data_t)arg; // a0: argument regs->a0 = (cpu_data_t)arg; // argument
regs->ra = (cpu_data_t)0xACE00ACE; // ra: return address regs->ra = (cpu_data_t)0xACE00ACE; // return address
regs->mstatus = (cpu_data_t)0x00001880; // return to machine mode and enable interrupt regs->mstatus = (cpu_data_t)0x00001880; // return to machine mode and enable interrupt
regs->mepc = (cpu_data_t)entry; regs->mepc = (cpu_data_t)entry; // task entry
return (k_stack_t*)sp; return (k_stack_t*)sp;
} }
@@ -173,4 +187,3 @@ __API__ uint32_t tos_cpu_clz(uint32_t val)
return (nbr_lead_zeros); return (nbr_lead_zeros);
} }

View File

@@ -146,56 +146,14 @@ port_sched_start:
lw t0, (t0) // t0 = &(k_curr_task->sp) lw t0, (t0) // t0 = &(k_curr_task->sp)
lw sp, (t0) // sp = k_curr_task->sp lw sp, (t0) // sp = k_curr_task->sp
// save sp to stack j restore_context
addi t1, sp, 128
sw t1, (t0)
// restore context
lw t0, __reg_mepc__OFFSET(sp)
csrw mepc, t0
lw t0, __reg_mstatus__OFFSET(sp)
csrw mstatus, t0
lw x3, __reg_x3_OFFSET(sp)
lw x4, __reg_x4_OFFSET(sp)
lw x5, __reg_x5_OFFSET(sp)
lw x6, __reg_x6_OFFSET(sp)
lw x7, __reg_x7_OFFSET(sp)
lw x8, __reg_x8_OFFSET(sp)
lw x9, __reg_x9_OFFSET(sp)
lw x10, __reg_x10_OFFSET(sp)
lw x11, __reg_x11_OFFSET(sp)
lw x12, __reg_x12_OFFSET(sp)
lw x13, __reg_x13_OFFSET(sp)
lw x14, __reg_x14_OFFSET(sp)
lw x15, __reg_x15_OFFSET(sp)
lw x16, __reg_x16_OFFSET(sp)
lw x17, __reg_x17_OFFSET(sp)
lw x18, __reg_x18_OFFSET(sp)
lw x19, __reg_x19_OFFSET(sp)
lw x20, __reg_x20_OFFSET(sp)
lw x21, __reg_x21_OFFSET(sp)
lw x22, __reg_x22_OFFSET(sp)
lw x23, __reg_x23_OFFSET(sp)
lw x24, __reg_x24_OFFSET(sp)
lw x25, __reg_x25_OFFSET(sp)
lw x26, __reg_x26_OFFSET(sp)
lw x27, __reg_x27_OFFSET(sp)
lw x28, __reg_x28_OFFSET(sp)
lw x29, __reg_x29_OFFSET(sp)
lw x30, __reg_x30_OFFSET(sp)
lw x31, __reg_x31_OFFSET(sp)
addi sp, sp, 128
mret
.align 2 .align 2
.type port_context_switch, %function .type port_context_switch, %function
port_context_switch: port_context_switch:
addi sp, sp, -128 addi sp, sp, -128
sw x1, __reg_x1_OFFSET(sp)
sw x3, __reg_x3_OFFSET(sp) sw x3, __reg_x3_OFFSET(sp)
sw x4, __reg_x4_OFFSET(sp) sw x4, __reg_x4_OFFSET(sp)
sw x5, __reg_x5_OFFSET(sp) sw x5, __reg_x5_OFFSET(sp)
@@ -226,7 +184,6 @@ port_context_switch:
sw x30, __reg_x30_OFFSET(sp) sw x30, __reg_x30_OFFSET(sp)
sw x31, __reg_x31_OFFSET(sp) sw x31, __reg_x31_OFFSET(sp)
sw ra, __reg_mepc_OFFSET(sp) sw ra, __reg_mepc_OFFSET(sp)
csrr t0, mstatus csrr t0, mstatus
@@ -234,20 +191,24 @@ port_context_switch:
or t0, t0, t1 or t0, t0, t1
sw t0, __reg_mstatus_OFFSET(sp) sw t0, __reg_mstatus_OFFSET(sp)
// save sp to k_curr_task.sp
la t0, k_curr_task // t0 = &k_curr_task la t0, k_curr_task // t0 = &k_curr_task
lw t1, (t0) la t1, k_next_task // t1 = &k_next_task
sw sp, (t1)
switch_task:
// save sp to k_curr_task.sp
lw t2, (t0)
sw sp, (t2)
// switch task // switch task
// k_curr_task = k_next_task // k_curr_task = k_next_task
la t1, k_next_task // t1 = &k_next_task
lw t1, (t1) // t1 = k_next_task lw t1, (t1) // t1 = k_next_task
sw t1, (t0) sw t1, (t0)
// load new task sp // load new task sp
lw sp, (t1) lw sp, (t1)
restore_context:
// restore context // restore context
lw t0, __reg_mepc_OFFSET(sp) lw t0, __reg_mepc_OFFSET(sp)
csrw mepc, t0 csrw mepc, t0
@@ -255,6 +216,7 @@ port_context_switch:
lw t0, __reg_mstatus_OFFSET(sp) lw t0, __reg_mstatus_OFFSET(sp)
csrw mstatus, t0 csrw mstatus, t0
lw x1, __reg_x1_OFFSET(sp)
lw x3, __reg_x3_OFFSET(sp) lw x3, __reg_x3_OFFSET(sp)
lw x4, __reg_x4_OFFSET(sp) lw x4, __reg_x4_OFFSET(sp)
lw x5, __reg_x5_OFFSET(sp) lw x5, __reg_x5_OFFSET(sp)
@@ -284,7 +246,6 @@ port_context_switch:
lw x29, __reg_x29_OFFSET(sp) lw x29, __reg_x29_OFFSET(sp)
lw x30, __reg_x30_OFFSET(sp) lw x30, __reg_x30_OFFSET(sp)
lw x31, __reg_x31_OFFSET(sp) lw x31, __reg_x31_OFFSET(sp)
addi sp, sp, 128 addi sp, sp, 128
mret mret
@@ -294,7 +255,6 @@ port_context_switch:
.global rv32_exception_entry .global rv32_exception_entry
rv32_exception_entry: rv32_exception_entry:
addi sp, sp, -128 addi sp, sp, -128
sw ra, __reg_ra__OFFSET(sp) sw ra, __reg_ra__OFFSET(sp)
sw gp, __reg_gp__OFFSET(sp) sw gp, __reg_gp__OFFSET(sp)
sw tp, __reg_tp__OFFSET(sp) sw tp, __reg_tp__OFFSET(sp)
@@ -320,54 +280,27 @@ rv32_exception_entry:
csrr t0, mstatus csrr t0, mstatus
sw t0, __reg_mstatus__OFFSET(sp) sw t0, __reg_mstatus__OFFSET(sp)
// switch to irq stack
mv t0, sp
la t1, k_irq_stk_top
lw sp, (t1)
sw t0, (sp)
// get irq num and call irq handler // get irq num and call irq handler
li t0, SOC_MCAUSE_EXP_MASK li t0, MCAUSE_EXP_CODE_MASK
csrr a0, mcause csrr a0, mcause
and a0, a0, t0 and a0, a0, t0
call cpu_irq_entry call cpu_irq_entry
// switch back to task stack
lw t0, (sp)
mv sp, t0
la t0, k_curr_task la t0, k_curr_task
la t1, k_next_task la t1, k_next_task
beq t0, t1, irq_restore // unlikely
bne t0, t1, irq_task_switch
sw s0, __reg_s0__OFFSET(sp)
sw s1, __reg_s1__OFFSET(sp)
sw s2, __reg_s2__OFFSET(sp)
sw s3, __reg_s3__OFFSET(sp)
sw s4, __reg_s4__OFFSET(sp)
sw s5, __reg_s5__OFFSET(sp)
sw s6, __reg_s6__OFFSET(sp)
sw s7, __reg_s7__OFFSET(sp)
sw s8, __reg_s8__OFFSET(sp)
sw s9, __reg_s9__OFFSET(sp)
sw s10, __reg_s10__OFFSET(sp)
sw s11, __reg_s11__OFFSET(sp)
// save sp to k_curr_task.sp
la t0, k_curr_task // t0 = &k_curr_task
lw t2, (t0) // t2 = k_curr_task->sp
sw sp, (t2) // k_curr_task->sp = sp
// switch task
lw t1, (t1) // t1 = k_next_task
sw t1, (t0) // k_curr_task = k_next_task
// load new task sp
lw sp, (t1)
lw s0, __reg_s0__OFFSET(sp)
lw s1, __reg_s1__OFFSET(sp)
lw s2, __reg_s2__OFFSET(sp)
lw s3, __reg_s3__OFFSET(sp)
lw s4, __reg_s4__OFFSET(sp)
lw s5, __reg_s5__OFFSET(sp)
lw s6, __reg_s6__OFFSET(sp)
lw s7, __reg_s7__OFFSET(sp)
lw s8, __reg_s8__OFFSET(sp)
lw s9, __reg_s9__OFFSET(sp)
lw s10, __reg_s10__OFFSET(sp)
lw s11, __reg_s11__OFFSET(sp)
irq_restore: irq_restore:
lw t0, __reg_mepc_OFFSET(sp) lw t0, __reg_mepc_OFFSET(sp)
@@ -398,4 +331,18 @@ irq_restore:
mret mret
irq_task_switch:
sw s0, __reg_s0__OFFSET(sp)
sw s1, __reg_s1__OFFSET(sp)
sw s2, __reg_s2__OFFSET(sp)
sw s3, __reg_s3__OFFSET(sp)
sw s4, __reg_s4__OFFSET(sp)
sw s5, __reg_s5__OFFSET(sp)
sw s6, __reg_s6__OFFSET(sp)
sw s7, __reg_s7__OFFSET(sp)
sw s8, __reg_s8__OFFSET(sp)
sw s9, __reg_s9__OFFSET(sp)
sw s10, __reg_s10__OFFSET(sp)
sw s11, __reg_s11__OFFSET(sp)
j switch_task

View File

@@ -23,7 +23,7 @@
#define CLINT_MTIMECMP 0x4000 #define CLINT_MTIMECMP 0x4000
#define CLINT_MTIME 0xBFF8 #define CLINT_MTIME 0xBFF8
#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF #define MCAUSE_EXP_CODE_MASK 0x7FFFFFFF
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
void port_cpu_init(); void port_cpu_init();

View File

@@ -48,6 +48,9 @@
// 配置TencentOS tiny空闲任务栈大小 // 配置TencentOS tiny空闲任务栈大小
#define TOS_CFG_IDLE_TASK_STK_SIZE 512u #define TOS_CFG_IDLE_TASK_STK_SIZE 512u
// 配置TencentOS tiny中断栈大小
#define TOS_CFG_IRQ_STK_SIZE 128u
// 配置TencentOS tiny的tick频率 // 配置TencentOS tiny的tick频率
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u #define TOS_CFG_CPU_TICK_PER_SECOND 1000u

View File

@@ -43,5 +43,6 @@
#define TOS_CFG_MMBLK_EN 1u #define TOS_CFG_MMBLK_EN 1u
#define TOS_CFG_IRQ_STK_SIZE 128u
#endif /* INC_TOS_CONFIG_H_ */ #endif /* INC_TOS_CONFIG_H_ */