简介:
GD32VF103 的FreeRtos 的任务调度时间片记录使用mtime,任务的上下文切换试用版msip 来进行切换,类似于arm-cortexm 中的pendsave 中断,对应的msip寄存器描述如下。
上述寄存器设置bit 0 为1 即可触发MSIP中断,对应的systick 中断中监测任务时间片是否需要切换,如果需要切换,就会触发msip 中断,对应代码如下。
对应的宏定义对应的vPortSetMSIPInt() 函数
#define portYIELD() port_MSIPSET_BIT;
#define port_MSIPSET_BIT vPortSetMSIPInt()
触发msip 软中断后,对应的msip 中断即会响应,对应的中断处理函数如下
/* -------------------------------------------------------------------------------------------------------- */ /** * @brife MSIP入口函数 */ .align 2 .globl MSIP_HANDLER MSIP_HANDLER: pushREGFILE sp // 保存通用寄存器 (x1 到 x31) 的值到栈 portSAVE_CONTEXT_EXCP sp // 保存 CSR 寄存器 (MSTATUS, MEPC, MSUBM, MCAUSE) 的值 mv a0, sp // 将栈指针 (sp) 保存到寄存器 a0 call vPortClearMSIPInt // 调用函数 vPortClearMSIPInt 来清除 MSIP 中断标志位 jal taskswitch // 跳转到任务切换函数,执行任务切换 portRESTORE_CONTEXT_EXCP sp // 恢复 CSR 寄存器的值 (MSTATUS, MEPC, MSUBM, MCAUSE) popREGFILE sp // 恢复通用寄存器的值 mret // 返回中断,恢复中断前的状态
其中任务taskswitch 函数实现如下,最终调用vPortYield 函数
vPortYield 函数如下:
vPortYield: mv sp, a0 _vPortYield: LOAD t0, pxCurrentTCB STORE sp, 0x0(t0) #ifdef __riscv_flen csrr t2, mstatus li t0, (0x3 << 13) and t1,t2,t0 bne t1,t0,1f pushVFPREGFILE sp 1: CONFIG_FS_CLEAN #endif STORE a1, 33 * REGBYTES(sp) #if USE_MSP csrr sp, CSR_MSCRATCH #endif csrs CSR_MSTATUS, MSTATUS_MIE jal vDoTaskSwitchContext csrc CSR_MSTATUS, MSTATUS_MIE LOAD sp, pxCurrentTCB LOAD sp, 0x0(sp) portRESTORE_CONTEXT_EXCP sp #ifdef __riscv_flen csrr t2, mstatus li t0, (0x3 << 13) and t1, t2, t0 bne t1, t0, 2f popVFPREGFILE sp 2: #endif popREGFILE sp mret
在vPortYield 函数中最终调用vDoTaskSwitchContext 函数切换到新的任务至pxCurrentTCB 之后根据切换后的任务TCB指针中获取执行任务的上下文环境,从而完成任务调度。
整个切换过程整理如下。