RISC-V 是基于精简指令集(RISC)原则的开源指令集架构(ISA),具有广泛的应用前景。本文将使用兆易创新的GD32VF103V-EVAL开发板,基于IAR EWRISC-V工具链,介绍如何将FreeRTOS移植到GD32VF103,并使用Percepio的Tracealyzer工具验证移植的结果。
GD32VF103 RISC-V内核 MCU
GD32VF103VBT6采用了Nuclei 的Bumblebee内核,支持RV32IMAC指令集;支持机器模式和用户模式,提高软件安全性。寄存器组包含32个通用寄存器、RISC-V标准的状态寄存器及内核自定义的CSR寄存器。内核提供了一个计时器单元(Timer Unit,TIMER),产生的计时器中断和软件中断可以用于RTOS时钟节拍处理和任务切换。
Bumblebee 内核提供了在 RISC-V CLIC 基础上优化而来的“改进型内核中断控制器(Enhanced Core Local Interrupt Controller, ECLIC)”,用于管理所有的中断源。ECLC的每个中断源可以配置为向量或非向量处理模式。
FreeRTOS和Tracealyzer
Amazon FreeRTOS目前应用非常广泛的一款RTOS,遵循MIT license。FreeRTOS提供了针对IAR及GCC工具链的标准RISC-V内核移植示例,支持32位及64位架构内核。FreeRTOS支持抢占和时间片轮询两种任务调度方式,支持无限数量的应用任务。
Tracealyzer工具运行在Windows或Linux PC上,可用于目标系统运行RTOS行为分析,能够快速、轻松地收集多任务软件有用和有意义的行为。可以快速集成到现有的开发环境,通过快照模式或流模式采集系统运行时数据。提供超过30种视图可视化RTOS运行时行为,,帮助开发人员解决问题,提高软件的可靠性,改善软件的性能。
FreeRTOS 移植到 GD32VF103
FreeRTOS内核绝大部分都采用C语言编写,只有与处理器相关的上下文切换采用汇编语言实现,目的是为了保证上下文切换的效率。移植的关键要点是实现:
1、开启和关闭中断的方式;
2. 进入和退出临界区的方式;
3、产生周期性的中断,作为系统的时钟节拍;
4、任务的上下文切换;
中断管理和临界区实现
GD32VF103的ECLIC中断控制器有一个中断目标阈值级别寄存器(mth),优先级别低于该阈值的中断将不会被响应。在移植FreeRTOS时,通过设置mth来实现开关中断,对于优先级别比阈值高的中断则不受FreeRTOS管理,中断不存在额外的延迟。
代码的临界区也称为代码的临界段,这部分代码在执行时不允许被打断。FreeRTOS的临界区通过关中断来实现,在进入临界段之前须关中断,而临界段代码执行完毕后,要立即开中断。
系统时钟节拍
操作系统都需要一个时钟节拍,以实现系统的延时、超时等与时间相关的处理。时钟节拍是特定的周期性中断,中断的周期就是节拍的时间。节拍的时间长短根据实际的应用决定,时钟节拍的频率越高,系统的开销就越大。
RISC-V架构定义了一个64位宽度的mtime计数器,当mtime的计数值增加到与mtimecmp寄存器预设的值相等时可以产生中断。选择mtime计数器来产生系统时钟节拍,根据mtime的时钟频率和系统节拍频率算出mtimecmp的值,当中断发生后通过改写 mtimecmp 或者 mtime 的值来清除中断。所以,使用mtime来产生FreeRTOS需要的时钟节拍。
实现上下文切换
上下文是某一时间点CPU的寄存器内容,FreeRTOS能够正确的完成任务调度的关键是上下文切换。上下文切换的过程包括:把即将退出运行态的任务的运行现场保存到它任务堆栈;从下一个要运行的任务的堆栈中恢复它的运行现场。上下文切换的时间应尽可能的短,所以一般由汇编代码编写,作为操作系统移植的一部分。
任务的调度有可能是在ISR中进行的,为了能在ISR退出之后能够执行上下文切换,实现上下文切换的代码一般是放在异常的处理程序中,并且该异常的优先级别设置为最低。任务调度完成之后,触发切换上下文的异常,在所有更高优先级别的中断退出之后异常服务程序开始执行。
RISC-V架构的处理器上,能够用来作为任务切换的异常有两种:ecall异常和软件中断。ecall异常通过调用ecall指令来触发;软件中断通过往msip寄存器写“1”触发,写“0”清除。GD32VF103的软件中断连接到ECLIC单元进行统一管理。本次FreeRTOS移植选用软件中断来作为上下文切换的实现机制,eclic_msip_handler()是软中断的ISR,切换上下文放在此ISR中。
3.1 移植文件修改
FreeRTOS与处理器相关的代码存在于port.c、portASM.s和portmacro.h三个文件当中,作为移植的部分。portmacro.h头文件定义了FreeRTOS使用的数据类型,进入和退出临界区的宏,实现开关中断的宏,以及触发和清除软件中断的宏。
portASM.s中用汇编实现vPortStartFirstTask()函数,用于启动第一个任务,它的核心操作是从pxCurrentTCB中取出当前就绪任务中优先级最高任务的堆栈指针SP,通过SP恢复寄存器现场。
实现软件中断的服务函数eclic_msip_handler(),将当前的寄存器现场(通用寄存器x1、x5~x31;机器模式状态寄存器mstatus;机器模式异常PC寄存器mepc)保存到当前在运行任务的堆栈当中,然后从pxCurrentTCB取出下一个就绪中优先级最高任务的堆栈指针SP恢复寄存器现场,完成任务的上下文切换。
port.c文件中重点实现堆栈初始化函数pxPortInitialiseStack(),启动FreeRTOS调度器时特定的处理函数xPortStartScheduler(),系统时钟节拍定时器初始化函数vPortSetupTimerInterrupt(),以及系统时钟节拍中断服务函数xPortSysTickHandler()。这几个函数分别需要根据RISC-V架构和GD32VF103微控制器硬件特性来实现其功能。
3.2移植测试和验证
验证移植是完全能正常工作采用调试和借助相应的辅助工具来进行。使用IAR EWRISC-V建立项目,在代码中创建两个以上任务进行调试,代码调试时需要验证:
1、通过在系统时钟节拍ISR和软件中断ISR中添加断点,结合RISC-V的mtime和mcycle寄存器验证系统时钟节拍正确产生,且软件中断能够正常触发。
2、启动第一个任务时,通过添加断点,查看从任务堆栈中恢复的寄存器内容是否跟堆栈初始化时写入的内容一致,从而测试pxPortInitialiseStack()和vPortStartFirstTask()函数的工作正确性。
3、在执行任务上下文切换时,在软件中断服务程序中添加加断点,单步执行,同时通过EWRISC-V的memory观察窗口查看压栈到当前任务堆栈中的内容是否跟对应的寄存器内容相同;在恢复下文时,检查从下一个执行任务堆栈中恢复的寄存器内容是否堆栈中的一致。验证eclic_msip_handler()软件中断服务函数的上下文切换正确性。
4、启动第一个任务和任务上下文切换的代码验证能正常工作,移植的FreeRTOS已可以实现基本的任务调度,接着再继续测试开关中断操作和临界区是否正常。测试开关中断需要增加另外一个外设中断,将其优先级别分别设置大于或小于mth阈值进行测试,代码中手动调用开关中断操作API,检测中断触发是否如设计的模式,验证FreeRTOS对中断的控制。同样的方法测试进入和退出临界区。
5、通过FreeRTOS系统服务调用测试,测试系统的各项服务,如信号量,消息队列、事件标志等服务能否正常。并测试在受FreeRTOS管理的ISR中发信号、消息等操作也正确。
基础调试测试都通过之后,已经基本可以验证移植是否成功。在此基础上还可以借助额外的工具继续验证,如EWRISC-V自带的FreeRTOS调试插件显示的信息进行确认。
EWRISC-V RTOS调试插件 – Task窗口
Tracealyzer分析软件的应用
移植跟踪记录器库(Trace Recorder library)
Tracealyzer的跟踪记录器库是运行在嵌入式目标端的一个软件库,与FreeRTOS项目集成在一起,负责记录RTOS在运行时的产生的事件。记录的事件如果是存储在位于RAM中的事件缓存,这种工作方式称为快照模式(Snapshot),如果是通过通讯端口实时发送到PC端软件,则工作在流模式(Streaming)。跟踪记录器库跟处理器硬件没有依赖,只需要使用一个高精度的定时器产生时间戳,为记录的事件添加时间信息。
RISC-V架构的处理器可以利用内核的mcycle计数器来产生时间戳,mcycle是一个64位的计数器,对CPU的周期进行计数,所以频率跟CPU时钟相同,精度非常高。mcycle由两个32位的寄存器组成,Tracealyzer只需要使用低32位寄存器。
跟踪并分析FreeRTOS
将Tracealyzer跟踪记录器库添加到EWRISC-V的FreeRTOS项目中,并进行必要的配置,工作在快照模式。在应用代码中创建4个任务,分别为Led1Task~Led3Task、ButtonTask,任务优先级依次递增,运行程序一段时间,将快照数据通过EWRISCV保存成Hex文件并加载到PC端的Tracealyzer中进行分析。
通过水平时间轴视图查看各个任务的执行情况:每个任务或中断占一行,从左向右为时间轴的方向,行中有色矩形为该任务或中断的一次执行实例。由时间轴窗口可以快速的预览整个运行过程中系统的执行情况概览,放大窗口的时间分辨率之后可以仔细了解任务执行时的相关的内核事件和时间信息。
Tracealyzer水平时间轴视图
通过跟踪到的事件和记录的时间戳信息,Tracealyzer能够生成多种视图来观测系统运行时存在的问题,例如设计缺陷导致的线程饥饿,死锁等,以及发现系统中不必要的延迟,帮助开发者解决系统的问题,提高嵌入式系统的实时性。这些问题使用传统调试手段都难以发现,而且效率低。
本文介绍了基于RISC-V指令集微控制器GD32VF103在IAR EWRISCV工具链上移植FreeRTOS的方法和过程,以及对移植的系统进行验证的方法。在此基础上移植Tracealyzer跟踪记录器库,并通过跟踪FreeRTOS系统运行进一步观测系统的运行,并对任务的执行进行了分析。
跟FreeRTOS的官方入门手册对比,感觉楼主帖子里很多干货啊。
目前还看不太懂,我继续学习。感谢分享!