RISC-V指令集体系结构(ISA)易于扩展,并且没有指定关于特定RISC-V微控制器或片上系统(SoC)实现的所有内容。因此,FreeRTOS RISC-V移植也是可扩展的-它提供了一个处理所有RISC-V实现共有的寄存器的基本移植,以及一组macros,实现硬件特定的特性和扩展。 1. 快速入门为RISC-V内核构建FreeRTOS,步骤如下: 1包含FreeRTOS内核源代码及RISC-V移植文件到工程中 2 确保汇编器的include路径中包含描述芯片实现细节的头文件 3在FreeRTOSConfig.h中定义一个常量或linker变量指定中断堆栈的地址 4在FreeRTOSConfig.h中定义configCLINT_BASE_ADDRESS 5 在汇编程序中,定义portasmHANDLER_INTERRUPT为芯片或工具提供的外部中断处理函数名称 6 安装FreeRTOS trap处理程序 2. FreeRTOS RISC-V移植特性FreeRTOS提供可轻松扩展以适应RISC-V特定架构扩展的基本移植包,目前移植代码仅支持32位和64位RISC-V内核的机器模式,实现了独立的中断堆栈,减少了RAM使用。 FreeRTOS RISC-V移植需要一个额外的头文件,描述芯片特定的扩展,该文件为freertos_risc-v_chip_specific_extensions.h,需要将该文件的路径包含到汇编器的include路径设置中。 3. FreeRTOSConfig.h文件设置如果RISC-V芯片包含core local interrupt(CLINT),需设置configCLINT_BASE_ADDRESS为CLINT的基地址,否则设为0。 4. 中断(系统)堆栈设置在ISR服务程序中调用任何c函数之前,移植代码切换到指定的中断(系统)堆栈。中断堆栈的内存地址可以在链接脚本中定义,或在FreeRTOS移植代码中作为静态分配的数组声明。在内存受限的MCU上,推荐使用链接脚本方式,可以将进入main()之后,启动调度器前使用的stack重用于中断堆栈。 4.1 静态定义数组作为中断栈在FreeRTOSConfig.h中,定义configISR_STACK_SIZE_WORDS的size,以字为单位(非字节)。 4.2 在linker脚本中定义中断栈声明liner变量__freertos_irq_stack_top,保存中断堆栈的高地址,使用这种方式需要修改liner脚本。 调度器启动前,main()中使用的堆栈在调度器启动后不再需要,因此理想情况下,通过设置_freertos_irq_stack_top等于分配给main()使用的堆栈的最高地址值,重用堆栈。例如,如果链接器脚本包含如下内容(实际使用的链接器脚本有所不同): .stack :ALIGN(0x10) { __stack_bottom = .; . += STACK_SIZE; __stack_top = .; } > ram __stack_top是一个linker变量,其值等于main()中使用堆栈的最高地址,本例中,设置__freertos_irq_stack_top的值等于__stack_top,在__stack_top之后定义__freertos_irq_stack_top,如下: .stack : ALIGN(0x10) { __stack_bottom = .; . += STACK_SIZE; __stack_top = .; __freertos_irq_stack_top= .; /* ADDED THIS LINE. */ } > ram 注意:内核中不检查中断堆栈中是否会溢出。 5. 必需的编译器和汇编器命令行选项不同的RISC-V实现提供了不同的外部中断handler,需要告诉FreeRTOS内核调用哪个外部中断处理程序,设置外部中断handler的名称步骤如下: 1 加载RISC-V芯片供应商提供的外部中断handler名称,中断handler必须有一个参数,该参数值为进入中断时,RISC-V的cause寄存器的值。例如, void external_interrupt_handler( uint32_t cause ); 2定义一个汇编宏porasmHANDLER_INTERRUPT,等于中断handler的名字。 如果使用GCC,可以通过添加汇编命令实现(假设中断handler为external_interrupt_handler): -DportasmHANDLE_INTERRUPT=external_interrupt_handler 注意:需在汇编器include path中添加freertos_risc_v_chip_specific_extensions.h文件的正确路径, 6. 安装FreeRTOS的trap handlerFreeRTOS trap handler名称为freertos_risc_v_trap_handler(),是所有中断和异常的统一入口。trap源是外部中断时,FreeRTOStrap handler调用外部中断处理程序。 安装trap处理程序方法如下: 1如果使用的RISC-V内核包含CLINT,freertos_risc_v_trap_handler()将自动安装。 2如果使用的RISC-V内核不包含CLINT,需手动安装freertos_risc_v_trap_handler(),可以通过修改启动代码实现。 注意:如果RISC-V芯片使用向量中断控制器,需为每个向量安装freertos_risc_v_trap_handler。 7. 移植到新的32/64位RISC-V实现freertos_risc_v_chip_specific_extensions.h文件包含下列宏,需配置: 1 portasmHAS_CLINT 如果RISC-V芯片包含CLINT,设置#define portasmHAS_CLINT为1,否则为0 2 portasmADDI tiONAL_CONTEXT_SIZE RISC-V指令集是可扩展的。因此RISC-V芯片可能包含额外的寄存器。 定义portasmADDITIONAL_CONTEXT_SIZE为目标芯片增加的寄存器数。如Vega 开发板的RI5CY核,包含6个额外的寄存器。因此#define portasmADDITIONAL_CONTEXT_SIZE 6 3 portasmSAVE_ADDITIONAL_REGISTERS portasmSAVE_ADDITIONAL_REGISTERS是一个汇编宏,用于实现芯片特定的寄存器保存,如果portasmADDITIONAL_REGISTERS不为0,需要 1减堆栈指针,创建足够的堆栈保存寄存器 2将额外的寄存器内容保存到创建的堆栈中。 .macro portasmSAVE_ADDITIONAL_REGISTERS addi sp, sp,-(portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE) sw xx0, 1 * portWORD_SIZE( sp ) sw xx1, 2 * portWORD_SIZE( sp ) sw xx2, 3 * portWORD_SIZE( sp ) .endm 4 portasmRESTORE_ADDITIONAL_REGISTERS 如果portasmADDITIONAL_REGISTERS不为0,需要 1从堆栈中读取额外的寄存器 2增加堆栈指针,删除保存寄存器占用的堆栈空间 .macroportasmRESTORE_ADDITIONAL_REGISTERS lw xx0, 1 * portWORD_SIZE( sp ) lw xx1, 2 * portWORD_SIZE( sp ) lw xx2, 3 * portWORD_SIZE( sp ) addi sp, sp,(portasmADDITIONAL_CONTEXT_SIZE * portWORD_SIZE) .endm
|