【嵌入式】FreeRTOS的移植、任务运行状态以及源码的优化改进

本文详细介绍了FreeRTOS移植过程中的关键点,包括注意事项、如何配置任务运行状态监视,以及对源码的优化以增加任务切换次数统计。通过这些步骤,开发者可以更好地理解和控制任务执行情况,提升软件的稳定性和可维护性。

前言

FreeRTOS因其简洁小巧、功能齐全而深受嵌入式领域欢迎,如下图所示,除Linux外,FreeRTOS为全球嵌入式领域市场份额最多的实时操作系统。与之对标的uCOS、RTX、ThreadX等都被远远的甩在其后。加之近年又被亚马逊收购,FreeRTOS的应用应该会进一步扩大。网上已有很多各实时操作系统的对比,我也使用过几种操作系统包括FreeRTOS、uCOS等,但FreeRTOS给我的最深的印象就是移植方便,能够针对不同芯片进行快速移植,并且该有的功能也都有了。
其实对于快速移植来说,其实无论是FreeRTOS、uCos、RT-thread等热门操作系统,其在arm上的移植过程无外乎四个方面:1.cpu无关源代码移植;2.cpu相关代码移植;3.SVC中断、Pending中断、滴答定时器中断的适配;4.系统的裁剪。其原理都是一样的:都是在以固定间隔的定时中断驱动,进而触发软中断,在中断函数中进行任务调度以及上下文切换。因此,理解了这个,无论什么系统,移植起来时心里就有了大体方向了。
在这里插入图片描述
本文包含以下内容(本文不适用于初学者,默认读者已有了良好的工程搭建基础,以及良好的嵌入式代码阅读、编写能力):
1 对FreeRTOS移植过程中的重点做简要说明;
2 讲解开发阶段需要用到的【任务运行状态监视】该如何配置;
3 针对实际软件稳定性对FreeRTOS的源码稍作修改,使得任务运行状态可根据自己的需求随意扩展。文中主要是在源码中增加了【任务切换次数】这个属性,在任务发生切换时进行自加,并能通过FreeRTOS自带的任务状态获取函数获取。

一、FreeRTOS移植的注意事项

由于移植教程网上已有很多,而且基于KEIL、IAR的工程Demo也不在少数,故本文不对FreeRTOS的移植过程作详细讲解,只讲大概步骤和主要的注意事项。
1.从【官网】下载源码后,将source目录下的c文件加入到工程中,将include目录拷贝到工程目录下,然后在source/portable目录下找到适合自己MCU内核的接口文件,并加入到工程中。
2.在Demo文件夹中找到适合自己MCU的文件夹,并将FreeRTOSConfig.h文件拷贝到工程目录下;
3.操作系统转起来需要在滴答定时器中断中定时运行调度函数、并依赖SVC异常处理函数获取当前任务控制块、依赖Pending中断来进行上下文切换。以上几个中断、异常时执行的函数都在source/portable目录下的文件port.c或portasm.s中给出,一般为汇编函数。FreeRTOS中分别如下命名:

xPortSysTickHandler
vPortSVCHandler
xPortPendSVHandler

而在启动文件的中断向量表中,以上三个中断、异常按如下命名:

SysTick_Handler  
SVC_Handler 
PendSV_Handler 

因此,当发生以上中断、异常时,为了能顺利调用FreeRTOS已经写好的调度、切换函数,需要在FreeRTOSConfig.h中作如下宏定义:

#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler

这样一来,FreeRTOS源码中的vPortSVCHandler、xPortPendSVHandler函数就被替换成了中断向量表中对应的中断服务函数,从而在中断发生时能进入FreeRTOS写好的调度、任务切换函数。
到这里,有人会问,不还有个xPortSysTickHandler吗,怎么没有替换。原因是现在的嵌入式系统,无论裸机还是跑操作系统,一般都使能滴答定时器中断,并在中断中对一个变量进行自加操作,从而使这个变量成为整个系统的时间戳。因此,系统一初始化我就配置了周期为1ms的滴答定时器中断,并在中断函数中进行了时间戳的自加,这样一来,只需要把xPortSysTickHandler函数放到滴答定时器的中断处理函数中即可,如下所示:

volatile static uint32_t uwTick = 0;

void uwTickInc(void)
{
	uwTick++;
}

uint32_t sys_getTick(void)
{
	return uwTick;
}

void SysTick_Handler(void)
{
	uwTickInc();
	xPortSysTickHandler();
}

如此一来,拥有了滴答定时器驱动的调度函数、用于上下文切换的Pending中断函数,FreeRTOS就可以跑起来了,具体的任务创建、系统开启等就不再赘述了。

二、任务运行状态的获取

开发阶段需要在长期运行、测试中发现并解决问题,因此获取每个任务的运行状态是很有必要的。好在FreeRTOS中也提供了这个功能,一般说来,系统的监视最好放在等级最高的任务中,这样才能保证能监视所有任务。FreeRTOS中开启任务运行状态获取主要分以下几步:
1.在FreeRTOSConfig.h中添加宏定义:

#define configUSE_TRACE_FACILITY	1
#define configGENERATE_RUN_TIME_STATS 1

这样一来,在空闲任务中就会统计各个任务运行的总耗时以及系统运行的总时长。既然说到时间统计了,那么定时器必不可少,在下一步中配置。
2.需要配置FreeRTOS给出的两个宏定义:

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE()

其中第一个是运行时间的定时器配置函数,第二个是定时器的时间戳获取函数。由于我们已经配置了1ms的滴答定时器,并创建了一个永远自加的时间戳变量,因此,这里的第一个宏定义可以直接为空,第二个宏定义配置为上文中的sys_getTick( )即可:

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE()      sys_getTick( )

3.在监视任务中调用uxTaskGetSystemState进行各个任务状态的获取:

void watch
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜老越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值