From e5a2334bb639f3e1a84b56132eae6ff074bcea7e Mon Sep 17 00:00:00 2001 From: Chen Peng Date: Thu, 28 May 2026 15:23:19 +0800 Subject: [PATCH] =?UTF-8?q?CH32V10X=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CPU/CH32V10x/cpu.h | 15 +- CPU/CH32V10x/os_port.c | 106 +++----- CPU/CH32V10x/os_port_gnu.S | 543 ++++++++++++++++++++++--------------- 3 files changed, 379 insertions(+), 285 deletions(-) diff --git a/CPU/CH32V10x/cpu.h b/CPU/CH32V10x/cpu.h index 5038e2b..24d1dd0 100644 --- a/CPU/CH32V10x/cpu.h +++ b/CPU/CH32V10x/cpu.h @@ -28,7 +28,10 @@ OS_STATIC_FORCE_INLINE os_uint_t cpu_save_disable_irq_in_isr(void){ os_uint_t result; - __asm volatile ("csrrw %0, mstatus, %1":"=r"(result):"r"(0x1800):"memory"); + __asm volatile ("csrrw %0, mstatus, %1" + :"=r"(result) + :"r"(0x1800) + :"memory"); return result; } @@ -44,4 +47,14 @@ void cpu_restore_irq_in_isr(os_uint_t value){ #define os_port_save_disable_irq cpu_save_disable_irq_in_isr #define os_port_restore_irq cpu_restore_irq_in_isr +OS_STATIC_FORCE_INLINE +void cpu_set_isr_sp(void){ + __asm volatile("csrrw sp,mscratch,sp"); +} + +OS_STATIC_FORCE_INLINE +void cpu_set_task_sp(void){ + __asm volatile("csrrw sp,mscratch,sp"); +} + #endif /*INCLUDED_CPU_H*/ diff --git a/CPU/CH32V10x/os_port.c b/CPU/CH32V10x/os_port.c index 8933664..d527a83 100644 --- a/CPU/CH32V10x/os_port.c +++ b/CPU/CH32V10x/os_port.c @@ -1,3 +1,4 @@ +#include #include "os_port.h" #include "os_stack.h" #include "os_macros.h" @@ -5,7 +6,6 @@ #include "os_compiler.h" #include "os_systick.h" #include "os_sched.h" -#include "os_isr.h" #include "cpu.h" /* ------------------------------------------------------------------------------------------------------------------ */ @@ -20,7 +20,7 @@ uint32_t _SysTick_Config(os_tick_t ticks) { - NVIC->CFGR = (CPU_KEY1<<16) | (1<<1/*NESTCTRL*/) | (1<<0/*HWSTKCTRL*/); /* 关闭硬件压栈和嵌套 */ + NVIC->CFGR = 0xFA050003; /* 关闭硬件压栈和嵌套 */ NVIC_SetPriority(SysTick_IRQn,0xf0); NVIC_SetPriority(Software_IRQn,0xf0); @@ -44,6 +44,38 @@ uint32_t _SysTick_Config(os_tick_t ticks) /* */ typedef struct { + os_uintptr_t mstatus; /* zero, 用于 mstatus 保存 */ + os_uintptr_t ra; /* 返回地址 */ + os_uintptr_t mepc; /* 栈指针, mepc */ + os_uintptr_t x3; /* 全局指针 */ + os_uintptr_t x4; /* 线程指针 */ + os_uintptr_t x5; /* 临时寄存器0 */ + os_uintptr_t x6; /* 临时寄存器1 */ + os_uintptr_t x7; /* 临时寄存器2 */ + os_uintptr_t x8; /* s0/fp */ + os_uintptr_t x9; /* 保存寄存器1 */ + os_uintptr_t a0; /* 函数参数/返回值 */ + os_uintptr_t x11; /* 函数参数 */ + os_uintptr_t x12; /* 函数参数 */ + os_uintptr_t x13; /* 函数参数 */ + os_uintptr_t x14; /* 函数参数 */ + os_uintptr_t x15; /* 函数参数 */ + os_uintptr_t x16; /* 函数参数 */ + os_uintptr_t x17; /* 函数参数 */ + os_uintptr_t x18; /* 保存寄存器 */ + os_uintptr_t x19; /* 保存寄存器 */ + os_uintptr_t x20; /* 保存寄存器 */ + os_uintptr_t x21; /* 保存寄存器 */ + os_uintptr_t x22; /* 保存寄存器 */ + os_uintptr_t x23; /* 保存寄存器 */ + os_uintptr_t x24; /* 保存寄存器 */ + os_uintptr_t x25; /* 保存寄存器 */ + os_uintptr_t x26; /* 保存寄存器 */ + os_uintptr_t x27; /* 保存寄存器 */ + os_uintptr_t x28; /* 临时寄存器 */ + os_uintptr_t x29; /* 临时寄存器 */ + os_uintptr_t x30; /* 临时寄存器 */ + os_uintptr_t x31; /* 临时寄存器 */ #if (OS_CFG_CPU_FPU_PRESENT) os_uintptr_t f0; os_uintptr_t f1; @@ -78,55 +110,23 @@ typedef struct { os_uintptr_t f30; os_uintptr_t f31; #endif - os_uintptr_t mstatus; /* zero, 用于 mstatus 保存 */ - os_uintptr_t ra; /* 返回地址 */ - os_uintptr_t mepc; /* 栈指针, mepc */ - os_uintptr_t x3; /* 全局指针 */ - os_uintptr_t x4; /* 线程指针 */ - os_uintptr_t x5; /* 临时寄存器0 */ - os_uintptr_t x6; /* 临时寄存器1 */ - os_uintptr_t x7; /* 临时寄存器2 */ - os_uintptr_t x8; /* s0/fp */ - os_uintptr_t x9; /* 保存寄存器1 */ - os_uintptr_t a0; /* 函数参数/返回值 */ - os_uintptr_t x11; /* 函数参数 */ - os_uintptr_t x12; /* 函数参数 */ - os_uintptr_t x13; /* 函数参数 */ - os_uintptr_t x14; /* 函数参数 */ - os_uintptr_t x15; /* 函数参数 */ - os_uintptr_t x16; /* 函数参数 */ - os_uintptr_t x17; /* 函数参数 */ - os_uintptr_t x18; /* 保存寄存器 */ - os_uintptr_t x19; /* 保存寄存器 */ - os_uintptr_t x20; /* 保存寄存器 */ - os_uintptr_t x21; /* 保存寄存器 */ - os_uintptr_t x22; /* 保存寄存器 */ - os_uintptr_t x23; /* 保存寄存器 */ - os_uintptr_t x24; /* 保存寄存器 */ - os_uintptr_t x25; /* 保存寄存器 */ - os_uintptr_t x26; /* 保存寄存器 */ - os_uintptr_t x27; /* 保存寄存器 */ - os_uintptr_t x28; /* 临时寄存器 */ - os_uintptr_t x29; /* 临时寄存器 */ - os_uintptr_t x30; /* 临时寄存器 */ - os_uintptr_t x31; /* 临时寄存器 */ }os_stack_frame_t; #define STACK_FRAME_SIZE sizeof(os_stack_frame_t) -#define MSTATUS_MPIE (1<<7) os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param , void* stack_base, os_size_t stack_size, void(*exit_entry)(void)){ os_uintptr_t stack_max = (os_uintptr_t)((uint8_t *) stack_base + stack_size); os_uintptr_t real_max = OS_ALIGN_DOWN(stack_max, OS_ALIGN_SIZE); /* 实际栈顶的位置,对齐后的位置 */ stack_size -= (stack_max - real_max); /* 实际栈大小 */ - + uint8_t value = 0x01; os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE); for(os_size_t i=0; imstatus = MSTATUS_MPIE; + p_frame->mstatus = 0x1880; p_frame->mepc = (os_uintptr_t)entry; p_frame->a0 = (os_uintptr_t)param; p_frame->ra = (os_uintptr_t)exit_entry; @@ -139,29 +139,6 @@ os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param return stack; } -//void os_port_disable_irq(void){ -// RISCV_disable_irq(); -//} -// -//void os_port_enable_irq(void){ -// RISCV_enable_irq(); -//} -// -//os_uint_t os_port_save_disable_irq(void){ -// return os_port_save_disable_irq_in_isr(); -//} -// -//void os_port_restore_irq(os_uint_t level){ -// os_port_restore_irq_in_isr(level); -//} - -//os_uint_t os_port_save_disable_irq_in_isr(void){ -// return RISCV_get_set_MSTATUS(0x1800); -//} - -//void os_port_restore_irq_in_isr(os_uint_t level){ -// RISCV_set_MSTATUS(level); -//} void os_sched(void){ os_sched_in_isr(); @@ -204,22 +181,21 @@ void os_port_context_switch(void* from_sp, void* to_sp){ g_os_port_switch_from_sp = from_sp; g_os_port_switch_to_sp = to_sp; g_os_port_context_switch_flag = OS_TRUE; - os_critical_leave_in_isr(); if(from_sp==0){ + os_critical_leave_in_isr(); os_port_context_switch_to((os_uintptr_t)to_sp); }else{ + os_critical_leave_in_isr(); os_port_send_context_switch_request(); } } -void SysTick_Handler(void) __attribute__((interrupt())); -void SysTick_Handler(void){ +void SysTick_Handler_C(void){ SysTick->CTLR=0; SysTick->CNTL0=0;SysTick->CNTL1=0;SysTick->CNTL2=0;SysTick->CNTL3=0; SysTick->CNTH0=0;SysTick->CNTH1=0;SysTick->CNTH2=0;SysTick->CNTH3=0; SysTick->CTLR=0x1; - // 调用系统心跳处理 os_systick_tick(); } diff --git a/CPU/CH32V10x/os_port_gnu.S b/CPU/CH32V10x/os_port_gnu.S index ef9e141..a773351 100644 --- a/CPU/CH32V10x/os_port_gnu.S +++ b/CPU/CH32V10x/os_port_gnu.S @@ -33,220 +33,286 @@ cpu_clz: #endif .section .text.os_port_context_switch_to,"ax",%progbits -.align 8 +.align 2 .func .global os_port_context_switch_to .extern os_port_on_switch_success os_port_context_switch_to: - /* machine mode, disable ISR */ - li t0, 0x1800 - csrw mstatus, t0 + li t0, 0x1800 + csrw mstatus, t0 // 1. 关中断 - /* first save interrupt stack */ - la t0, _eusrstack - addi t0, t0, -512 - csrw mscratch,t0 + /* 设置中断栈/系统栈空间 */ + la t0, _eusrstack + addi t0, t0, -512 + csrw mscratch, t0 // 备用栈指针存入 mscratch - /* restore sp */ - LOAD sp, (a0) + /* ===================================================================== + * 第一步:切换到中断栈,安全调用通知 C 函数 + * ===================================================================== */ + jal os_port_on_switch_success // 调用 C 函数(此时随便它怎么污染寄存器) - csrrw sp, mscratch, sp - jal os_port_on_switch_success - csrrw sp, mscratch, sp + /* ===================================================================== + * 第二步:获取新任务的栈指针 SP + * ===================================================================== */ + LOAD sp, 0(a0) // a0 是传入的 &g_os_port_switch_to_sp,从中取出 sp - /* restore mstatus.MPIE */ - LOAD a0, 0*REG_BYTES(sp) - csrs mstatus, a0 - - /* restore mepc */ - LOAD a0, 2 * REG_BYTES(sp) - csrw mepc, a0 - - /* return address */ - LOAD x1, 1 * REG_BYTES(sp) - LOAD x4, 4 * REG_BYTES(sp) - LOAD x5, 5 * REG_BYTES(sp) - LOAD x6, 6 * REG_BYTES(sp) - LOAD x7, 7 * REG_BYTES(sp) - LOAD x8, 8 * REG_BYTES(sp) - LOAD x9, 9 * REG_BYTES(sp) - LOAD x10, 10 * REG_BYTES(sp) - LOAD x11, 11 * REG_BYTES(sp) - LOAD x12, 12 * REG_BYTES(sp) - LOAD x13, 13 * REG_BYTES(sp) - LOAD x14, 14 * REG_BYTES(sp) - LOAD x15, 15 * REG_BYTES(sp) - LOAD x16, 16 * REG_BYTES(sp) - LOAD x17, 17 * REG_BYTES(sp) - LOAD x18, 18 * REG_BYTES(sp) - LOAD x19, 19 * REG_BYTES(sp) - LOAD x20, 20 * REG_BYTES(sp) - LOAD x21, 21 * REG_BYTES(sp) - LOAD x22, 22 * REG_BYTES(sp) - LOAD x23, 23 * REG_BYTES(sp) - LOAD x24, 24 * REG_BYTES(sp) - LOAD x25, 25 * REG_BYTES(sp) - LOAD x26, 26 * REG_BYTES(sp) - LOAD x27, 27 * REG_BYTES(sp) - LOAD x28, 28 * REG_BYTES(sp) - LOAD x29, 29 * REG_BYTES(sp) - LOAD x30, 30 * REG_BYTES(sp) - LOAD x31, 31 * REG_BYTES(sp) - addi sp, sp, CONTEXT_SIZE - - /* load float reg */ -#if (OS_CFG_CPU_MPU_PRESENT) - FLOAD f0, 0 * REG_BYTES(sp) - FLOAD f1, 1 * REG_BYTES(sp) - FLOAD f2, 2 * REG_BYTES(sp) - FLOAD f3, 3 * REG_BYTES(sp) - FLOAD f4, 4 * REG_BYTES(sp) - FLOAD f5, 5 * REG_BYTES(sp) - FLOAD f6, 6 * REG_BYTES(sp) - FLOAD f7, 7 * REG_BYTES(sp) - FLOAD f8, 8 * REG_BYTES(sp) - FLOAD f9, 9 * REG_BYTES(sp) - FLOAD f10, 10 * REG_BYTES(sp) - FLOAD f11, 11 * REG_BYTES(sp) - FLOAD f12, 12 * REG_BYTES(sp) - FLOAD f13, 13 * REG_BYTES(sp) - FLOAD f14, 14 * REG_BYTES(sp) - FLOAD f15, 15 * REG_BYTES(sp) - FLOAD f16, 16 * REG_BYTES(sp) - FLOAD f17, 17 * REG_BYTES(sp) - FLOAD f18, 18 * REG_BYTES(sp) - FLOAD f19, 19 * REG_BYTES(sp) - FLOAD f20, 20 * REG_BYTES(sp) - FLOAD f21, 21 * REG_BYTES(sp) - FLOAD f22, 22 * REG_BYTES(sp) - FLOAD f23, 23 * REG_BYTES(sp) - FLOAD f24, 24 * REG_BYTES(sp) - FLOAD f25, 25 * REG_BYTES(sp) - FLOAD f26, 26 * REG_BYTES(sp) - FLOAD f27, 27 * REG_BYTES(sp) - FLOAD f28, 28 * REG_BYTES(sp) - FLOAD f29, 29 * REG_BYTES(sp) - FLOAD f30, 30 * REG_BYTES(sp) - FLOAD f31, 31 * REG_BYTES(sp) - addi sp, sp, 32 * REG_BYTES + /* ===================================================================== + * 第三步:恢复 FPU 浮点寄存器(与保存栈帧严格镜像) + * 修复宏定义:将 MPU 改回 FPU + * ===================================================================== */ +#if (OS_CFG_CPU_FPU_PRESENT) + FLOAD f0, (CONTEXT_SIZE + 0 * REG_BYTES)(sp) + FLOAD f1, (CONTEXT_SIZE + 1 * REG_BYTES)(sp) + FLOAD f2, (CONTEXT_SIZE + 2 * REG_BYTES)(sp) + FLOAD f3, (CONTEXT_SIZE + 3 * REG_BYTES)(sp) + FLOAD f4, (CONTEXT_SIZE + 4 * REG_BYTES)(sp) + FLOAD f5, (CONTEXT_SIZE + 5 * REG_BYTES)(sp) + FLOAD f6, (CONTEXT_SIZE + 6 * REG_BYTES)(sp) + FLOAD f7, (CONTEXT_SIZE + 7 * REG_BYTES)(sp) + FLOAD f8, (CONTEXT_SIZE + 8 * REG_BYTES)(sp) + FLOAD f9, (CONTEXT_SIZE + 9 * REG_BYTES)(sp) + FLOAD f10, (CONTEXT_SIZE + 10 * REG_BYTES)(sp) + FLOAD f11, (CONTEXT_SIZE + 11 * REG_BYTES)(sp) + FLOAD f12, (CONTEXT_SIZE + 12 * REG_BYTES)(sp) + FLOAD f13, (CONTEXT_SIZE + 13 * REG_BYTES)(sp) + FLOAD f14, (CONTEXT_SIZE + 14 * REG_BYTES)(sp) + FLOAD f15, (CONTEXT_SIZE + 15 * REG_BYTES)(sp) + FLOAD f16, (CONTEXT_SIZE + 16 * REG_BYTES)(sp) + FLOAD f17, (CONTEXT_SIZE + 17 * REG_BYTES)(sp) + FLOAD f18, (CONTEXT_SIZE + 18 * REG_BYTES)(sp) + FLOAD f19, (CONTEXT_SIZE + 19 * REG_BYTES)(sp) + FLOAD f20, (CONTEXT_SIZE + 20 * REG_BYTES)(sp) + FLOAD f21, (CONTEXT_SIZE + 21 * REG_BYTES)(sp) + FLOAD f22, (CONTEXT_SIZE + 22 * REG_BYTES)(sp) + FLOAD f23, (CONTEXT_SIZE + 23 * REG_BYTES)(sp) + FLOAD f24, (CONTEXT_SIZE + 24 * REG_BYTES)(sp) + FLOAD f25, (CONTEXT_SIZE + 25 * REG_BYTES)(sp) + FLOAD f26, (CONTEXT_SIZE + 26 * REG_BYTES)(sp) + FLOAD f27, (CONTEXT_SIZE + 27 * REG_BYTES)(sp) + FLOAD f28, (CONTEXT_SIZE + 28 * REG_BYTES)(sp) + FLOAD f29, (CONTEXT_SIZE + 29 * REG_BYTES)(sp) + FLOAD f30, (CONTEXT_SIZE + 30 * REG_BYTES)(sp) + FLOAD f31, (CONTEXT_SIZE + 31 * REG_BYTES)(sp) #endif + /* ===================================================================== + * 第四步:恢复通用寄存器(最后恢复 t0) + * ===================================================================== */ + LOAD x1, 1 * REG_BYTES(sp) + LOAD x4, 4 * REG_BYTES(sp) + LOAD x6, 6 * REG_BYTES(sp) + LOAD x7, 7 * REG_BYTES(sp) + LOAD x8, 8 * REG_BYTES(sp) + LOAD x9, 9 * REG_BYTES(sp) + LOAD x10, 10 * REG_BYTES(sp) + LOAD x11, 11 * REG_BYTES(sp) + LOAD x12, 12 * REG_BYTES(sp) + LOAD x13, 13 * REG_BYTES(sp) + LOAD x14, 14 * REG_BYTES(sp) + LOAD x15, 15 * REG_BYTES(sp) + LOAD x16, 16 * REG_BYTES(sp) + LOAD x17, 17 * REG_BYTES(sp) + LOAD x18, 18 * REG_BYTES(sp) + LOAD x19, 19 * REG_BYTES(sp) + LOAD x20, 20 * REG_BYTES(sp) + LOAD x21, 21 * REG_BYTES(sp) + LOAD x22, 22 * REG_BYTES(sp) + LOAD x23, 23 * REG_BYTES(sp) + LOAD x24, 24 * REG_BYTES(sp) + LOAD x25, 25 * REG_BYTES(sp) + LOAD x26, 26 * REG_BYTES(sp) + LOAD x27, 27 * REG_BYTES(sp) + LOAD x28, 28 * REG_BYTES(sp) + LOAD x29, 29 * REG_BYTES(sp) + LOAD x30, 30 * REG_BYTES(sp) + LOAD x31, 31 * REG_BYTES(sp) + + /* ===================================================================== + * 第五步:恢复特权级控制 CSR 寄存器 + * ===================================================================== */ + LOAD t0, 2 * REG_BYTES(sp) // 恢复初始 PC 到 mepc + csrw mepc, t0 + + LOAD t0, 0 * REG_BYTES(sp) // 从栈中读取准备好的初始 mstatus + csrw mstatus, t0 // 修复:改用 csrw 强行覆盖 + + LOAD x5, 5 * REG_BYTES(sp) // 此时最后安全恢复 t0(x5) + + /* ===================================================================== + * 第六步:统一释放栈空间并退出 + * ===================================================================== */ +#if (OS_CFG_CPU_FPU_PRESENT) + addi sp, sp, (CONTEXT_SIZE + 32 * REG_BYTES) +#else + addi sp, sp, CONTEXT_SIZE +#endif mret .endfunc .section .text.SW_Handler,"ax",%progbits -.align 8 +.align 2 .func .global SW_Handler .extern g_os_port_switch_from_sp .extern g_os_port_switch_to_sp -.extern os_isr_enter -.extern os_isr_leave .extern os_port_on_switch_success -.extern g_t0 SW_Handler: + csrci mstatus, 0x08 // 立刻关闭全局中断 MIE = 0 + + /* ===================================================================== + * 第一步:一揽子分配所有栈空间(防止碎片和二次偏移错误) + * ===================================================================== */ #if (OS_CFG_CPU_FPU_PRESENT) - addi sp, sp, -32 * REG_BYTES - FSTORE f0, 0 * REG_BYTES(sp) - FSTORE f1, 1 * REG_BYTES(sp) - FSTORE f2, 2 * REG_BYTES(sp) - FSTORE f3, 3 * REG_BYTES(sp) - FSTORE f4, 4 * REG_BYTES(sp) - FSTORE f5, 5 * REG_BYTES(sp) - FSTORE f6, 6 * REG_BYTES(sp) - FSTORE f7, 7 * REG_BYTES(sp) - FSTORE f8, 8 * REG_BYTES(sp) - FSTORE f9, 9 * REG_BYTES(sp) - FSTORE f10, 10 * REG_BYTES(sp) - FSTORE f11, 11 * REG_BYTES(sp) - FSTORE f12, 12 * REG_BYTES(sp) - FSTORE f13, 13 * REG_BYTES(sp) - FSTORE f14, 14 * REG_BYTES(sp) - FSTORE f15, 15 * REG_BYTES(sp) - FSTORE f16, 16 * REG_BYTES(sp) - FSTORE f17, 17 * REG_BYTES(sp) - FSTORE f18, 18 * REG_BYTES(sp) - FSTORE f19, 19 * REG_BYTES(sp) - FSTORE f20, 20 * REG_BYTES(sp) - FSTORE f21, 21 * REG_BYTES(sp) - FSTORE f22, 22 * REG_BYTES(sp) - FSTORE f23, 23 * REG_BYTES(sp) - FSTORE f24, 24 * REG_BYTES(sp) - FSTORE f25, 25 * REG_BYTES(sp) - FSTORE f26, 26 * REG_BYTES(sp) - FSTORE f27, 27 * REG_BYTES(sp) - FSTORE f28, 28 * REG_BYTES(sp) - FSTORE f29, 29 * REG_BYTES(sp) - FSTORE f30, 30 * REG_BYTES(sp) - FSTORE f31, 31 * REG_BYTES(sp) + addi sp, sp, -(CONTEXT_SIZE + 32 * REG_BYTES) +#else + addi sp, sp, -CONTEXT_SIZE #endif - addi sp, sp, -CONTEXT_SIZE // 留出栈空间 - STORE t0, 5*REG_BYTES(sp) // 保存 t0 - - li t0, 0x80 - STORE t0, 0 * REG_BYTES(sp) // 设置 MPIE - - csrr t0, mepc - STORE t0, 2*REG_BYTES(sp) // 保存正在运行任务的 pc 指针 - - STORE x1, 1 * REG_BYTES(sp) // return address - STORE x4, 4 * REG_BYTES(sp) - STORE x6, 6 * REG_BYTES(sp) - STORE x7, 7 * REG_BYTES(sp) - STORE x8, 8 * REG_BYTES(sp) - STORE x9, 9 * REG_BYTES(sp) - STORE x10, 10 * REG_BYTES(sp) - STORE x11, 11 * REG_BYTES(sp) - STORE x12, 12 * REG_BYTES(sp) - STORE x13, 13 * REG_BYTES(sp) - STORE x14, 14 * REG_BYTES(sp) - STORE x15, 15 * REG_BYTES(sp) - STORE x16, 16 * REG_BYTES(sp) - STORE x17, 17 * REG_BYTES(sp) - STORE x18, 18 * REG_BYTES(sp) - STORE x19, 19 * REG_BYTES(sp) - STORE x20, 20 * REG_BYTES(sp) - STORE x21, 21 * REG_BYTES(sp) - STORE x22, 22 * REG_BYTES(sp) - STORE x23, 23 * REG_BYTES(sp) - STORE x24, 24 * REG_BYTES(sp) - STORE x25, 25 * REG_BYTES(sp) - STORE x26, 26 * REG_BYTES(sp) - STORE x27, 27 * REG_BYTES(sp) - STORE x28, 28 * REG_BYTES(sp) - STORE x29, 29 * REG_BYTES(sp) - STORE x30, 30 * REG_BYTES(sp) - STORE x31, 31 * REG_BYTES(sp) - - la s0, g_os_port_switch_from_sp - LOAD s1, 0(s0) - STORE sp, 0(s1) // 将 sp 存入 g_os_port_switch_from_sp - - // 切换到 isr stack - csrrw sp,mscratch,sp - jal os_port_on_switch_success - csrrw sp,mscratch,sp - - la s0, g_os_port_switch_to_sp - LOAD s1, 0(s0) - LOAD sp, 0(s1) // 将 sp 指向 g_os_port_switch_to_sp 栈 - - LOAD a0, 2 * REG_BYTES(sp) // 加载/恢复 mepc - csrw mepc, a0 - - LOAD x1, 1*REG_BYTES(sp) + /* ===================================================================== + * 第二步:保存通用寄存器 + * ===================================================================== */ + STORE x5, 5 * REG_BYTES(sp) // 优先保存 t0,腾出临时寄存器 li t0, 0x1800 - csrs mstatus, t0 // 确保 M 模式 + csrw mstatus, t0 // M 模式 - LOAD t0, 0*REG_BYTES(sp) // 加载 mstatus - csrs mstatus, t0 // 恢复 mstatus + li t0, 0x1880 + STORE t0, 0 * REG_BYTES(sp) // 设置 MPIE + csrr t0, mepc + STORE t0, 2*REG_BYTES(sp) // 保存正在运行任务的 pc 指针 + + STORE x1, 1 * REG_BYTES(sp) // ra + STORE x4, 4 * REG_BYTES(sp) // tp + STORE x6, 6 * REG_BYTES(sp) // t1 + STORE x7, 7 * REG_BYTES(sp) // t2 + STORE x8, 8 * REG_BYTES(sp) // s0/fp + STORE x9, 9 * REG_BYTES(sp) // s1 + STORE x10, 10 * REG_BYTES(sp) // a0 + STORE x11, 11 * REG_BYTES(sp) // a1 + STORE x12, 12 * REG_BYTES(sp) // a2 + STORE x13, 13 * REG_BYTES(sp) // a3 + STORE x14, 14 * REG_BYTES(sp) // a4 + STORE x15, 15 * REG_BYTES(sp) // a5 + STORE x16, 16 * REG_BYTES(sp) // a6 + STORE x17, 17 * REG_BYTES(sp) // a7 + STORE x18, 18 * REG_BYTES(sp) // s2 + STORE x19, 19 * REG_BYTES(sp) // s3 + STORE x20, 20 * REG_BYTES(sp) // s4 + STORE x21, 21 * REG_BYTES(sp) // s5 + STORE x22, 22 * REG_BYTES(sp) // s6 + STORE x23, 23 * REG_BYTES(sp) // s7 + STORE x24, 24 * REG_BYTES(sp) // s8 + STORE x25, 25 * REG_BYTES(sp) // s9 + STORE x26, 26 * REG_BYTES(sp) // s10 + STORE x27, 27 * REG_BYTES(sp) // s11 + STORE x28, 28 * REG_BYTES(sp) // t3 + STORE x29, 29 * REG_BYTES(sp) // t4 + STORE x30, 30 * REG_BYTES(sp) // t5 + STORE x31, 31 * REG_BYTES(sp) // t6 + +/* ===================================================================== + * 第三步:保存 FPU 浮点寄存器(使用确定的、不受干扰的高位偏移) + * ===================================================================== */ +#if (OS_CFG_CPU_FPU_PRESENT) + FSTORE f0, (CONTEXT_SIZE + 0 * REG_BYTES)(sp) + FSTORE f1, (CONTEXT_SIZE + 1 * REG_BYTES)(sp) + FSTORE f2, (CONTEXT_SIZE + 2 * REG_BYTES)(sp) + FSTORE f3, (CONTEXT_SIZE + 3 * REG_BYTES)(sp) + FSTORE f4, (CONTEXT_SIZE + 4 * REG_BYTES)(sp) + FSTORE f5, (CONTEXT_SIZE + 5 * REG_BYTES)(sp) + FSTORE f6, (CONTEXT_SIZE + 6 * REG_BYTES)(sp) + FSTORE f7, (CONTEXT_SIZE + 7 * REG_BYTES)(sp) + FSTORE f8, (CONTEXT_SIZE + 8 * REG_BYTES)(sp) + FSTORE f9, (CONTEXT_SIZE + 9 * REG_BYTES)(sp) + FSTORE f10, (CONTEXT_SIZE + 10 * REG_BYTES)(sp) + FSTORE f11, (CONTEXT_SIZE + 11 * REG_BYTES)(sp) + FSTORE f12, (CONTEXT_SIZE + 12 * REG_BYTES)(sp) + FSTORE f13, (CONTEXT_SIZE + 13 * REG_BYTES)(sp) + FSTORE f14, (CONTEXT_SIZE + 14 * REG_BYTES)(sp) + FSTORE f15, (CONTEXT_SIZE + 15 * REG_BYTES)(sp) + FSTORE f16, (CONTEXT_SIZE + 16 * REG_BYTES)(sp) + FSTORE f17, (CONTEXT_SIZE + 17 * REG_BYTES)(sp) + FSTORE f18, (CONTEXT_SIZE + 18 * REG_BYTES)(sp) + FSTORE f19, (CONTEXT_SIZE + 19 * REG_BYTES)(sp) + FSTORE f20, (CONTEXT_SIZE + 20 * REG_BYTES)(sp) + FSTORE f21, (CONTEXT_SIZE + 21 * REG_BYTES)(sp) + FSTORE f22, (CONTEXT_SIZE + 22 * REG_BYTES)(sp) + FSTORE f23, (CONTEXT_SIZE + 23 * REG_BYTES)(sp) + FSTORE f24, (CONTEXT_SIZE + 24 * REG_BYTES)(sp) + FSTORE f25, (CONTEXT_SIZE + 25 * REG_BYTES)(sp) + FSTORE f26, (CONTEXT_SIZE + 26 * REG_BYTES)(sp) + FSTORE f27, (CONTEXT_SIZE + 27 * REG_BYTES)(sp) + FSTORE f28, (CONTEXT_SIZE + 28 * REG_BYTES)(sp) + FSTORE f29, (CONTEXT_SIZE + 29 * REG_BYTES)(sp) + FSTORE f30, (CONTEXT_SIZE + 30 * REG_BYTES)(sp) + FSTORE f31, (CONTEXT_SIZE + 31 * REG_BYTES)(sp) +#endif + + /* ===================================================================== + * 第四步:保存旧任务 sp,并安全调用通知函数 + * ===================================================================== */ + la t0, g_os_port_switch_from_sp + LOAD t0, 0(t0) + STORE sp, 0(t0) // 将 sp 存入 g_os_port_switch_from_sp + + // 此时调用 C 函数是完全安全的,因为所有寄存器都已在任务栈里备考 + jal os_port_on_switch_success + + /* ===================================================================== + * 第五步:载入新任务的栈指针(SP) + * ===================================================================== */ + la t0, g_os_port_switch_to_sp + LOAD t0, 0(t0) + LOAD sp, 0(t0) // 将 sp 指向 g_os_port_switch_to_sp 栈 + + /* ===================================================================== + * 第六步:恢复新任务的 FPU 浮点寄存器 + * ===================================================================== */ +#if (OS_CFG_CPU_FPU_PRESENT) + FLOAD f0, (CONTEXT_SIZE + 0 * REG_BYTES)(sp) + FLOAD f1, (CONTEXT_SIZE + 1 * REG_BYTES)(sp) + FLOAD f2, (CONTEXT_SIZE + 2 * REG_BYTES)(sp) + FLOAD f3, (CONTEXT_SIZE + 3 * REG_BYTES)(sp) + FLOAD f4, (CONTEXT_SIZE + 4 * REG_BYTES)(sp) + FLOAD f5, (CONTEXT_SIZE + 5 * REG_BYTES)(sp) + FLOAD f6, (CONTEXT_SIZE + 6 * REG_BYTES)(sp) + FLOAD f7, (CONTEXT_SIZE + 7 * REG_BYTES)(sp) + FLOAD f8, (CONTEXT_SIZE + 8 * REG_BYTES)(sp) + FLOAD f9, (CONTEXT_SIZE + 9 * REG_BYTES)(sp) + FLOAD f10, (CONTEXT_SIZE + 10 * REG_BYTES)(sp) + FLOAD f11, (CONTEXT_SIZE + 11 * REG_BYTES)(sp) + FLOAD f12, (CONTEXT_SIZE + 12 * REG_BYTES)(sp) + FLOAD f13, (CONTEXT_SIZE + 13 * REG_BYTES)(sp) + FLOAD f14, (CONTEXT_SIZE + 14 * REG_BYTES)(sp) + FLOAD f15, (CONTEXT_SIZE + 15 * REG_BYTES)(sp) + FLOAD f16, (CONTEXT_SIZE + 16 * REG_BYTES)(sp) + FLOAD f17, (CONTEXT_SIZE + 17 * REG_BYTES)(sp) + FLOAD f18, (CONTEXT_SIZE + 18 * REG_BYTES)(sp) + FLOAD f19, (CONTEXT_SIZE + 19 * REG_BYTES)(sp) + FLOAD f20, (CONTEXT_SIZE + 20 * REG_BYTES)(sp) + FLOAD f21, (CONTEXT_SIZE + 21 * REG_BYTES)(sp) + FLOAD f22, (CONTEXT_SIZE + 22 * REG_BYTES)(sp) + FLOAD f23, (CONTEXT_SIZE + 23 * REG_BYTES)(sp) + FLOAD f24, (CONTEXT_SIZE + 24 * REG_BYTES)(sp) + FLOAD f25, (CONTEXT_SIZE + 25 * REG_BYTES)(sp) + FLOAD f26, (CONTEXT_SIZE + 26 * REG_BYTES)(sp) + FLOAD f27, (CONTEXT_SIZE + 27 * REG_BYTES)(sp) + FLOAD f28, (CONTEXT_SIZE + 28 * REG_BYTES)(sp) + FLOAD f29, (CONTEXT_SIZE + 29 * REG_BYTES)(sp) + FLOAD f30, (CONTEXT_SIZE + 30 * REG_BYTES)(sp) + FLOAD f31, (CONTEXT_SIZE + 31 * REG_BYTES)(sp) +#endif + + + /* ===================================================================== + * 第七步:全面恢复通用寄存器(最后恢复 t0) + * ===================================================================== */ + LOAD x1, 1 * REG_BYTES(sp) LOAD x4, 4 * REG_BYTES(sp) - LOAD x5, 5 * REG_BYTES(sp) +// LOAD x5, 5 * REG_BYTES(sp) // 恢复 t0 LOAD x6, 6 * REG_BYTES(sp) LOAD x7, 7 * REG_BYTES(sp) LOAD x8, 8 * REG_BYTES(sp) @@ -273,49 +339,88 @@ SW_Handler: LOAD x29, 29 * REG_BYTES(sp) LOAD x30, 30 * REG_BYTES(sp) LOAD x31, 31 * REG_BYTES(sp) - addi sp, sp, CONTEXT_SIZE // 恢复栈指针 -/* load float reg */ + + /* ===================================================================== + * 第八步:恢复新任务的 CSR 寄存器 + * ===================================================================== */ + LOAD t0, 2 * REG_BYTES(sp) // 恢复 mepc + csrw mepc, t0 + + LOAD t0, 0 * REG_BYTES(sp) // 恢复 mstatus + csrw mstatus, t0 + + LOAD x5, 5 * REG_BYTES(sp) // 恢复 t0 + + /* ===================================================================== + * 第九步:彻底释放栈空间并退出 + * ===================================================================== */ #if (OS_CFG_CPU_FPU_PRESENT) - FLOAD f0, 0 * REG_BYTES(sp) - FLOAD f1, 1 * REG_BYTES(sp) - FLOAD f2, 2 * REG_BYTES(sp) - FLOAD f3, 3 * REG_BYTES(sp) - FLOAD f4, 4 * REG_BYTES(sp) - FLOAD f5, 5 * REG_BYTES(sp) - FLOAD f6, 6 * REG_BYTES(sp) - FLOAD f7, 7 * REG_BYTES(sp) - FLOAD f8, 8 * REG_BYTES(sp) - FLOAD f9, 9 * REG_BYTES(sp) - FLOAD f10, 10 * REG_BYTES(sp) - FLOAD f11, 11 * REG_BYTES(sp) - FLOAD f12, 12 * REG_BYTES(sp) - FLOAD f13, 13 * REG_BYTES(sp) - FLOAD f14, 14 * REG_BYTES(sp) - FLOAD f15, 15 * REG_BYTES(sp) - FLOAD f16, 16 * REG_BYTES(sp) - FLOAD f17, 17 * REG_BYTES(sp) - FLOAD f18, 18 * REG_BYTES(sp) - FLOAD f19, 19 * REG_BYTES(sp) - FLOAD f20, 20 * REG_BYTES(sp) - FLOAD f21, 21 * REG_BYTES(sp) - FLOAD f22, 22 * REG_BYTES(sp) - FLOAD f23, 23 * REG_BYTES(sp) - FLOAD f24, 24 * REG_BYTES(sp) - FLOAD f25, 25 * REG_BYTES(sp) - FLOAD f26, 26 * REG_BYTES(sp) - FLOAD f27, 27 * REG_BYTES(sp) - FLOAD f28, 28 * REG_BYTES(sp) - FLOAD f29, 29 * REG_BYTES(sp) - FLOAD f30, 30 * REG_BYTES(sp) - FLOAD f31, 31 * REG_BYTES(sp) - addi sp, sp, 32 * REG_BYTES + addi sp, sp, (CONTEXT_SIZE + 32 * REG_BYTES) +#else + addi sp, sp, CONTEXT_SIZE #endif +/* 执行 mret。此时: + * 1. 硬件会自动把当前 mstatus.MPIE (1) 复制到 mstatus.MIE,从而开启全局中断。 + * 2. 程序跳转到 mepc 寄存器指向的地址(即新任务继续运行的代码处)。 */ mret // 从 M 模式退出 .endfunc +.section .text.SysTick_Handler,"ax",%progbits +.align 2 +.global SysTick_Handler +.extern SysTick_Handler_C +.func +SysTick_Handler: +// csrci mstatus, 8 // 关闭中断 + /* 1. 因为是硬件中断,先在当前栈上保存必要的临时寄存器(Caller-saved) */ + addi sp, sp, -16 * REG_BYTES + STORE x1, 0 * REG_BYTES(sp) # ra + STORE x5, 1 * REG_BYTES(sp) # t0 + STORE x6, 2 * REG_BYTES(sp) # t1 + STORE x7, 3 * REG_BYTES(sp) # t2 + STORE x10, 4 * REG_BYTES(sp) # a0 + STORE x11, 5 * REG_BYTES(sp) # a1 + STORE x12, 6 * REG_BYTES(sp) # a2 + STORE x13, 7 * REG_BYTES(sp) # a3 + STORE x14, 8 * REG_BYTES(sp) # a4 + STORE x15, 9 * REG_BYTES(sp) # a5 + STORE x16, 10 * REG_BYTES(sp) # a6 + STORE x17, 11 * REG_BYTES(sp) # a7 + STORE x28, 12 * REG_BYTES(sp) # t3 + STORE x29, 13 * REG_BYTES(sp) # t4 + STORE x30, 14 * REG_BYTES(sp) # t5 + STORE x31, 15 * REG_BYTES(sp) # t6 + + /* 2. 清除定时器硬件中断标志位(防止重复触发),并调用 C 语言的时钟处理函数 */ + jal SysTick_Handler_C + + /* 3. 恢复临时寄存器 */ + LOAD x1, 0 * REG_BYTES(sp) # ra + LOAD x5, 1 * REG_BYTES(sp) # t0 + LOAD x6, 2 * REG_BYTES(sp) # t1 + LOAD x7, 3 * REG_BYTES(sp) # t2 + LOAD x10, 4 * REG_BYTES(sp) # a0 + LOAD x11, 5 * REG_BYTES(sp) # a1 + LOAD x12, 6 * REG_BYTES(sp) # a2 + LOAD x13, 7 * REG_BYTES(sp) # a3 + LOAD x14, 8 * REG_BYTES(sp) # a4 + LOAD x15, 9 * REG_BYTES(sp) # a5 + LOAD x16, 10 * REG_BYTES(sp) # a6 + LOAD x17, 11 * REG_BYTES(sp) # a7 + LOAD x28, 12 * REG_BYTES(sp) # t3 + LOAD x29, 13 * REG_BYTES(sp) # t4 + LOAD x30, 14 * REG_BYTES(sp) # t5 + LOAD x31, 15 * REG_BYTES(sp) # t6 + + addi sp, sp, 16 * REG_BYTES + + /* 4. 退出硬件中断 */ + mret + .endfunc + .align 4 .end \ No newline at end of file