平头哥E90X异常处理

上下文入栈保存

    addi sp, sp, -portCONTEXT_SIZE          ----开辟一段栈空间,这里的sp可能是主栈或任务栈
    store_x x1, 1 * portWORD_SIZE( sp )     ----依次存储相关寄存器
    store_x x5, 2 * portWORD_SIZE( sp )
    store_x x6, 3 * portWORD_SIZE( sp )
    store_x x7, 4 * portWORD_SIZE( sp )
    store_x x8, 5 * portWORD_SIZE( sp )
    store_x x9, 6 * portWORD_SIZE( sp )
    store_x x10, 7 * portWORD_SIZE( sp )
    store_x x11, 8 * portWORD_SIZE( sp )
    store_x x12, 9 * portWORD_SIZE( sp )
    store_x x13, 10 * portWORD_SIZE( sp )
    store_x x14, 11 * portWORD_SIZE( sp )
    store_x x15, 12 * portWORD_SIZE( sp )
    store_x x16, 13 * portWORD_SIZE( sp )
    store_x x17, 14 * portWORD_SIZE( sp )
    store_x x18, 15 * portWORD_SIZE( sp )
    store_x x19, 16 * portWORD_SIZE( sp )
    store_x x20, 17 * portWORD_SIZE( sp )
    store_x x21, 18 * portWORD_SIZE( sp )
    store_x x22, 19 * portWORD_SIZE( sp )
    store_x x23, 20 * portWORD_SIZE( sp )
    store_x x24, 21 * portWORD_SIZE( sp )
    store_x x25, 22 * portWORD_SIZE( sp )
    store_x x26, 23 * portWORD_SIZE( sp )
    store_x x27, 24 * portWORD_SIZE( sp )
    store_x x28, 25 * portWORD_SIZE( sp )
    store_x x29, 26 * portWORD_SIZE( sp )
    store_x x30, 27 * portWORD_SIZE( sp )
    store_x x31, 28 * portWORD_SIZE( sp )
    store_x x3,  31 * portWORD_SIZE( sp )
    store_x x4,  32 * portWORD_SIZE( sp )

    mv a0, sp
    addi a0, a0, portCONTEXT_SIZE
    store_x a0,  30 * portWORD_SIZE( sp )  ---将栈起始地址保存到栈空间中

    csrr a0, mepc
    store_x a0,  0 * portWORD_SIZE( sp )   ---将mepc保存到栈空间中
    csrr t0, mscratch
    store_x t0, 33 * portWORD_SIZE( sp )   ---将mscratch保存到栈空间中

    csrr t0, mstatus                    /* Required for MPIE bit. */
    store_x t0, 29 * portWORD_SIZE( sp )   将mstatus保存到栈空间中

    load_x  t0, pxCurrentTCB            /* Load pxCurrentTCB. */
    store_x  sp, 0( t0 )                /* Write sp to first TCB member. */
                                         将sp写入pxCurrentTCB->pxTopOfStack
                               即将sp保存到任务的控制块中,每个任务都有一个全局的控制块
                               当恢复的时候,也是通过pxCurrentTCB先获取到sp。

检查是同步异常

    csrr a0, mcause        ---a0=mcause
    csrr a1, mepc          ---a1=mepc

test_if_asynchronous:
    srli a2, a0, __riscv_xlen - 1   --将a0右移63位(64位系统),即获取mcause最高位,赋值为a2
    beq a2, x0, handle_synchronous --判断a2是否为0,如果是0,则是同步异常,跳转处理,否则是中断。

异常处理

handle_synchronous:
    csrr t0, mcause         --获取mcasue到t0中
    andi t0, t0, 0x7ff     
    mv   a0, t0
    addi a1, a1, 4      
    store_x a1, 0( sp ) 

test_if_environment_call:
    li t0, 11                   
    bne a0, t0, is_exception            
    load_x sp, xISRStackTop         
    call vTaskSwitchContext
    j processed_source

is_exception:
    csrr t0, mcause                 
    csrr t1, mepc                   
    csrr t2, mtval
    mv   a0, t0
    mv   a1, t1
    mv   a2, t2
    mv   a3, sp
    call enter_interrupt_handler
    call riscv_cpu_handle_exception          ----异常处理函数
    call exit_interrupt_handler
    j is_exception                      

上下文出栈

    load_x  t1, pxCurrentTCB            /* Load pxCurrentTCB. */
    load_x  sp, 0( t1 )                 /* Read sp from first TCB member. */


    load_x t0, 0( sp ) --获取中断返回后,要执行的PC,其保存在栈的第一个位置
    csrw mepc, t0  


    /* Load mstatus with the interrupt enable bits used by the task. */
    load_x  t0, 29 * portWORD_SIZE( sp )
    csrw mstatus, t0                        恢复mstatus(打开中断)

    load_x  x1, 1 * portWORD_SIZE( sp )
    load_x  x5, 2 * portWORD_SIZE( sp )     /* t0 */
    load_x  x6, 3 * portWORD_SIZE( sp )     /* t1 */
    load_x  x7, 4 * portWORD_SIZE( sp )     /* t2 */
    load_x  x8, 5 * portWORD_SIZE( sp )     /* s0/fp */
    load_x  x9, 6 * portWORD_SIZE( sp )     /* s1 */
    load_x  x10, 7 * portWORD_SIZE( sp )    /* a0 */
    load_x  x11, 8 * portWORD_SIZE( sp )    /* a1 */
    load_x  x12, 9 * portWORD_SIZE( sp )    /* a2 */
    load_x  x13, 10 * portWORD_SIZE( sp )   /* a3 */
    load_x  x14, 11 * portWORD_SIZE( sp )   /* a4 */
    load_x  x15, 12 * portWORD_SIZE( sp )   /* a5 */
    load_x  x16, 13 * portWORD_SIZE( sp )   /* a6 */
    load_x  x17, 14 * portWORD_SIZE( sp )   /* a7 */
    load_x  x18, 15 * portWORD_SIZE( sp )   /* s2 */
    load_x  x19, 16 * portWORD_SIZE( sp )   /* s3 */
    load_x  x20, 17 * portWORD_SIZE( sp )   /* s4 */
    load_x  x21, 18 * portWORD_SIZE( sp )   /* s5 */
    load_x  x22, 19 * portWORD_SIZE( sp )   /* s6 */
    load_x  x23, 20 * portWORD_SIZE( sp )   /* s7 */
    load_x  x24, 21 * portWORD_SIZE( sp )   /* s8 */
    load_x  x25, 22 * portWORD_SIZE( sp )   /* s9 */
    load_x  x26, 23 * portWORD_SIZE( sp )   /* s10 */
    load_x  x27, 24 * portWORD_SIZE( sp )   /* s11 */
    load_x  x28, 25 * portWORD_SIZE( sp )   /* t3 */
    load_x  x29, 26 * portWORD_SIZE( sp )   /* t4 */
    load_x  x30, 27 * portWORD_SIZE( sp )   /* t5 */
    load_x  x31, 28 * portWORD_SIZE( sp )   /* t6 */
    addi sp, sp, portCONTEXT_SIZE        -----栈空间释放

    mret        ---中断返回