PolarFire® SoC 尝试移植 FreeRTOS (二)
书接上回:PolarFire® SoC 尝试移植 FreeRTOS (一) - 所长 - 博客园
Using FreeRTOS on RISC-V Microcontrollers - FreeRTOS™
安装 FreeRTOS 陷阱处理程序
FreeRTOS 陷阱处理程序称为 freertos_risc_v_trap_handler(),而 是所有中断和异常的中心入口点。The FreeRTOS 当陷阱的源是外部中断时,陷阱处理程序调用外部中断处理程序。
要安装陷阱处理程序:
-
如果正在使用的 RISC-V 内核包含内核本地中断器 (CLINT),则 portasmHAS_SIFIVE_CLINT可以定义为 1 在 freertos_risc_v_chip_specific_extensions.h 中, 这导致自动安装 freertos_risc_v_trap_handler(), 因此不需要其他特定作。
-
在所有其他情况下,必须安装 freertos_risc_v_trap_handler() 手动地。这可以通过编辑您提供的启动代码来完成 芯片提供商。
注意:如果 RISC-V 芯片使用矢量中断控制器,则安装 freertos_risc_v_trap_handler() 作为每个向量的处理程序。
我使用的是 ;"${workspace_loc:/${ProjName}/src/FreeRTOS/port/RISC-V/chip_specific_extensions/RISCV_MTIME_CLINT_no_extensions}"
#define portasmHAS_SIFIVE_CLINT 1
#define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 0
按照 portasmHAS_SIFIVE_CLINT可以定义为 1 在 freertos_risc_v_chip_specific_extensions.h 中, 这导致自动安装 freertos_risc_v_trap_handler(), 因此不需要其他特定作。
仿真调试代码, 进入异常中断,值为 11 , 即
#define CAUSE_MACHINE_ECALL 0xb
当异常处理程序(在 mtvec 指向的地址)开始执行时,如果读取 mcause 寄存器的值发现是 11(或 0xB),就可以断定这次异常是因为在 M-mode 执行了 ecall 指令;
问题已解决 : 方法:使用 汇编指令 修改 当前内核 对应的 异常/中断向量寄存器,MTVEC, 指向 FreeRTOS 向量表
第一步 : 首先 参考 FreeRTOS/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/main.c at main · FreeRTOS/FreeRTOS 添加 下面函数
#define mainVECTOR_MODE_DIRECT 0
extern void freertos_risc_v_trap_handler( void );
extern void freertos_vector_table( void );
#if ( mainVECTOR_MODE_DIRECT == 1 )
{
__asm__ volatile ( "csrw mtvec, %0" : : "r" ( freertos_risc_v_trap_handler ) );
}
#else
{
__asm__ volatile ( "csrw mtvec, %0" : : "r" ( ( uintptr_t ) freertos_vector_table | 0x1 ) ); // 使用 向量模式, 接管 中断
}
#endif
复制 vector_table.S 文件 FreeRTOS/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/vector_table.S at main · FreeRTOS/FreeRTOS
到 工程 所在目录
编译 整个工程 , 发现 任务已经可以正常 跑起来!
void x_system_task( void * arg ) { for(;;) { MSS_UART_polled_tx(p_uartmap_u54_1,"x_system_task\n", 14 ); vTaskDelay(1000); } }

FreeRTOS 跑起来,没问题, 但是 由于 FreeRTOS 重映射了 中断向量表,相当于接管了,整个芯片的 中断, 其他外设 中断 如何处理? 比如一个串口 外设 ?
FreeRTOS 接管中断后 ,外设产生中断时, 函数调用顺序如下:
向量模式下,会自动跳到 freertos_vector_table 对应的 freertos_risc_v_interrupt_handler 然后调用 → freertos_risc_v_application_interrupt_handler 处理
因此在 main,c 中定义 freertos_risc_v_application_interrupt_handler 函数 ,下面为 处理串口1 本地中断的例子
void freertos_risc_v_application_interrupt_handler( void ) { volatile uintptr_t mcause = read_csr(mcause); xprintf( "irq:0x%llX.\n", mcause ); if((mcause&0x7FFFFFFFFFFFFFFF) == 27) { U54_1_mmuart1_local_IRQHandler(); } }
为什么 27 是 串口1的本地中断 ,详细看 PolarFire® SoC mpfs-mmuart-interrupt 串口1 本地中断 初始化过程 - 所长 - 博客园
同样 异常 函数 处理 如下 :
void freertos_risc_v_application_exception_handler( void ) { volatile uintptr_t mcause = read_csr(mcause); xprintf( "ERROR:risc_v exception mcause:0x%llX.\n", mcause ); while(1); }
浙公网安备 33010602011771号