1、异常处理函数的注册
对RISC-V架构中断不熟悉,可参考博客:《RISC-V架构——中断处理和中断控制器介绍》;
2、异常处理函数分析
2.1、数调用关系
freertos_risc_v_trap_handler //异常处理函数入口portcontextSAVE_CONTEXT_INTERNAL //保存任务切换上下文asynchronous_interrupt //异步异常:时钟中断handle_interrupt //异步异常:时钟中断portUPDATE_MTIMER_COMPARE_REGISTER//更新产生时钟中断的时间xTaskIncrementTick//决定是否切换任务processed_source//中断返回,恢复中断现场vTaskSwitchContext//切换上下文processed_source//中断返回,恢复任务上下文synchronous_exception //同步异常:ecall调用handle_exceptionvTaskSwitchContext//切换任务processed_source//中断返回,恢恢复任务上下文
2.2、源码
.section .text.freertos_risc_v_trap_handler
.align 8
freertos_risc_v_trap_handler: //异常处理入口函数portcontextSAVE_CONTEXT_INTERNAL //保存任务上下文csrr a0, mcause //读取mcause寄存csrr a1, mepc //读取发生异常时候的地址//注意这里把mcause中读出来的数当做符号数,高位1表示负数//异常异常时,mcause寄存器的高位是1(负数);同步异常,mcause寄存的高位是0bge a0, x0, synchronous_exception //异步异常:时钟中断
asynchronous_interrupt:store_x a1, 0( sp ) //保存发生异常返回的地址 load_x sp, xISRStackTop //切换到中断特有的栈空间, xISRStackTop记录的栈顶j handle_interrupt//同步异常:ecall调用
synchronous_exception:addi a1, a1, 4 //mepc的值+4,这里只处理ecall调用,所以默认+4。并不是所有的同步异常都要+4store_x a1, 0( sp ) //保存发生异常返回的地址load_x sp, xISRStackTop //切换到中断特有的栈空间, xISRStackTop记录的栈顶j handle_exceptionhandle_interrupt:
#if( portasmHAS_MTIME != 0 )test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */addi t0, x0, 1slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */bne a0, t1, application_interrupt_handlerportUPDATE_MTIMER_COMPARE_REGISTER //更新产生时钟中断的时间call xTaskIncrementTick //决定是否切换任务beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */call vTaskSwitchContext //切换上下文j processed_source#endif /* portasmHAS_MTIME */application_interrupt_handler:call freertos_risc_v_application_interrupt_handlerj processed_source//任务主动切换,调用ecall进入中断
handle_exception:/* a0 contains mcause. */li t0, 11 /* 11表示是M模式的系统调用 */bne a0, t0, application_exception_handler /* 不是ecall调用,则执行application_exception_handler */call vTaskSwitchContext //切换任务j processed_sourceapplication_exception_handler:call freertos_risc_v_application_exception_handler //死循环j processed_source /* No other exceptions handled yet. */processed_source:portcontextRESTORE_CONTEXT //中断返回,恢复任务上下文
FreeRTOSv202212.01\FreeRTOS\Source\portable\GCC\RISC-V\portASM.S