发 帖  
原厂入驻New
申请华秋企业认证 多层板首单免费打样!
30s提交资料,10分钟通过审核(免费赔付+顺丰包邮)>>立即报名

[经验] 如何在RISC-V处理器上使用FreeRTOS?

2019-11-29 15:54:41  2190 RISC-V FreeRTOS
分享
1
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 handler
FreeRTOS 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 portasmADDItiONAL_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

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
关闭

站长推荐 上一条 /5 下一条

快速回复 返回顶部 返回列表