FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
任务调度机制是嵌入式实时操作系统的一个重要概念,也是其核心技术。对于可剥夺型内核,优先级高的任务一旦就绪就能剥夺优先级较低任务的CPU使用权,提高了系统的实时响应能力。不同于μC/OS-II,FreeRTOS对系统任务的数量没有限制,既支持优先级调度算法也支持轮换调度算法,因此FreeRTOS采用双向链表而不是采用查任务就绪表的方法来进行任务调度。
系统定义的链表和链表节点数据结构如下所示:
//定义链表结构
typedef struct xLIST{
unsigned portSHORPT usNumberOfItems; //usNumberOfItems为链表的长度,为0表示链表为空
volatile xListItem *pxHead; //pxHead为链表的头指针
volatile xListItem *pxIndex; //pxIndex指向链表当前结点的指针
volatile xListItem xListEnd; //xListEnd为链表尾结点
}xList;
//定义链表结点的结构
struct xLIST_ITEM{
port Tick type; //port Type为时针节拍数据类型
xItem Value; //xItem Value的值用于实现时间管理,可根据需要选择为16位或32位
volatile struct xLIST_ITEM *pxNext; //指向链表的前一个结点
void *pvOwner; //指向此链表结点所在的任务控制块
void *pvContainer; //指向此链表结点所在的链表
};
每当任务、队列和信号量创建的时候,FreeRTOS要求分配一定的RAM。虽然采用malloc()和free()函数可以实现申请和释放内存的功能,但这两个函数存在以下缺点:并不是在所有的嵌入式系统中都可用,要占用不定的程序空间,可重入性欠缺以及执行时间具有不可确定性。为此,除了可采用malloc()和free()函数外,FreeRTOS还提供了另外两种内存分配的策略,用户可以根据实际需要选择不同的内存分配策略。
第1种方法是,按照需求内存的大小简单地把一大块内存分割为若干小块,每个小块的大小对应于所需求内存的大小。这样做的好处是比较简单,执行时间可严格确定,适用于任务和队列全部创建完毕后再进行内核调度的系统;这样做的缺点是,由于内存不能有效释放,系统运行时应用程序并不能实现删除任务或队列。
第2种方法是,采用链表分配内存,可实现动态的创建、删除任务或队列。系统根据空闲内存块的大小按从小到大的顺序组织空闲内存链表。当应用程序申请一块内存时,系统根据申请内存的大小按顺序搜索空闲内存链表,找到满足申请内存要求的最小空闲内存块。为了提高内存的使用效率,在空闲内存块比申请内存大的情况下,系统会把此空闲内存块一分为二。一块用于满足申请内存的要求,一块作为新的空闲内存块插入到链表中。
方法2的优点是,能根据任务需要高效率地使用内存,尤其是当不同的任务需要不同大小的内存的时候。方法2的缺点是,不能把应用程序释放的内存和原有的空闲内存混合为一体,因此,若应用程序频繁申请与释放“随机”大小的内存,就可能造成大量的内存碎片。方法2的另一个缺点是,程序执行时间具有一定的不确定性。
FreeRTOS中每个任务对应于一个任务控制块(TCB),其定义如下所示:
typedef struct tasTaskContralBlock{
portSTACK_TYPE *pxTopOfStack; //指向任务堆栈结束处
portSTACK_TYPE *pxStack; //指向任务堆栈起始处
unsigned portSHORT usStackDepth; //定义堆栈深度
signed portCHAR pcTaskName[tskMAX_TASK_NAME_LEN]; //任务名称
unsigned portCHAR ucPriority; //任务优先级
xListItem xGenericListItem; //用于把TCB插入就绪表或等待链表
xListItem xEventListItem; //用于把TCB插入事件链表(如消息队列)
unsigned portCHAR ucTCBNumber; //用于记录功能
}tskTCB;
作为一个轻量级的操作系统,FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能等,可基本满足较小系统的需要。FreeRTOS内核支持优先级调度算法,每个任务可根据重要程度的不同被赋予一定的优先级,CPU总是让处于就绪态的、优先级最高的任务先运行。FreeRTOS内核同时支持轮换调度算法,系统允许不同的任务使用相同的优先级,在没有更高优先级任务就绪的情况下,同一优先级的任务共享CPU的使用时间。
FreeRTOS的内核可根据用户需要设置为可剥夺型内核或不可剥夺型内核。当FreeRTOS被设置为可剥夺型内核时,处于就绪态的高优先级任务能剥夺低优先级任务的CPU使用权,这样可保证系统满足实时性的要求;当FreeRTOS被设置为不可剥夺型内核时,处于就绪态的高优先级任务只有等当前运行任务主动释放CPU的使用权后才能获得运行,这样可提高CPU的运行效率。