引言:本文介绍了FreeRTOS实时OS的基本功能,以及在SAM微控制器上如何配置和使用FreeRTOS的基本功能。本文涵盖了一下几大块内容:
l 什么是Real-Time的应用以及什么是实时操作系统
l 如何创建并配置一个FreeRTOS的项目
l 如何使用FreeRTOS的基本功能
l 如何使用图形化Debug工具来跟踪实时OS的系统执行
本文的示例是基于Atmel Software Framework(ASF)的,凡是基于SAM器件并使用高于ASF3.8.1版本的ASF都可以编译通过。
1、关于RTOS的一些基本概念
1.1 什么是实时应用程序
实时应用程序和普通程序的区别就在于执行操作的时间。一个实时的应用会在一个可以预知的时间(并且这个时间是可以确定)内执行有关的操作,例如一个实时的应用可以确保用户在按下ESC键以后0.2ms结束数据的发送,而不是启动某个结束线程,并且这个线程的执行是需要系统按照优先级调度的。通常情况下,一个实时系统的需求会分为软实时(soft real-time)和硬实时(Hard real-time)需求,在系统设计的时候要综合考虑这两方面需求:
l 软实时需求:当时间底限被破坏的时候,整个系统的可用性不会被破坏,只是带来体验上的延时。
l 硬实时需求:当时间底限被破坏以后,整个系统失败。例如:安全气囊如果在指定的时间内没有弹出,保护系统将失效。
1.2 实时系统和多任务
对于大多数操作系统来说,支持多任务是一个最基本的特性。在多任务的基础上,网络、外设接口和用户界面等等的支持才能被引入。嵌入式系统并不用支持全部的上述接口,只需要选择性的支持一部分。嵌入式系统所选用的操作系统通常只含有对多任务基本功能的支持。这些操作系统的体积大小不一,从300字节到10K字节不等。但他们都足够小,一边装入微控制器的内部闪存。
一个实时的操作系统通常包括以下的多任务特性:
l 多任务并发运行
l 调度器来决定哪个任务运行
l 调度器可以抢占一个正在运行的任务的资源
l 支持任务间的通信
1.3 FreeRTOS的介绍
FreeRTOS是个实时系统的内核,很多基于Contex –M3/M4的应用程序可以在这个内核的基础上构建,以满足对于硬实时性的需求。多数Context-M3/M4系列的微控制器只有一个内核,所以在任意时刻,只有一个任务可以运行。内核(调度器)根据分配给每个任务的优先级来决定哪个任务在哪个时刻运行。通常而言,应用设计者可以为硬实时性高的任务分配较高的优先级,对实时性较低的任务分配较低的优先级,以确保硬实时需求比软实时需求有更高的优先级。
1.3.1 FreeRTOS的内核
FreeRTOS的内核是目标无关的,并且作为独立的组件被集成在Atmel Software Framework里发布。可以使用Atmel Studio的ASF向导将内核模块加入到任何标准工程中,或者使用手动方式向在IAR中向独立的ASF工程文件中添加。
图 FreeRTOS模块的组成
Cortex- M3/M4/M0+ port包括所有标准的FreeRTOS的特征:
l Pre-emptive和Co-operation的操作
l 具有柔性的任务优先级分配
l 软时钟
l 二进制信号量
l 反射信号量
l 计数信号量
l 互斥
l Tick hook functions
l 空闲钩挂函数
l 栈溢出检查
l “跟踪”钩挂的宏定义
1.3.2 FreeRTOS的多任务管理机制
FreeRTOS允许在同一时刻处理多个任务,但只能有一个任务运行(单核)。因此,系统需要一个调度器将时间片分配给各个任务。调度器是FreeRTOS内核的核心,它依据分配给任务的优先级和它的状态来选择要运行的任务。任务状态的转换和任务的调度如下图:
图 任务的状态和调度过程中状态的转换
l 总状态:运行态和非运行态
l 非运行态分为:Suspended、ready和Blocked三个子状态
l Suspend:任务被应用程序挂起(deactivated)
l Blocked:为获得同步事件任务被阻塞
l Ready:任务准备运行,但有更高级别的任务正在运行。
任务调度的时候,瞄准那些“ready”状态的任务并决定哪些任务可以被执行。FreeRTOS根据任务被创建时分配的优先级来决定。任务的优先级是调度器判断和执行调度时考虑的唯一要素。每一次时钟的滴答都会促使调度器考虑哪个任务需要被唤醒。
图 内核和任务之间的调度关系
内核代码(调度器)负责在两个任务之间协调时间片的分配。当第一个任务(Task1)从运行状态变到非运行状态的时候,例如,程序运行结束,主程序main()调用Return,系统的都会自动调用调度器代码,调度器会按照调度算法从所有当前是“ready”的任务中选择一个运行。从上图可见,调度器的运行时间都很短,对于Task的运行时间可以忽略不计。
1.3.3 FreeRTOS的内存管理
FreeRTOS没有设置Task数量的上限,只要配套的硬件和内存可以支持如此众多的任务。FreeRTOS作为一个实时的操作系统,可以支持周期性和非周期性的任务。
图 任务的内存分配
系统的内核在每创建一个任务或者一个内核对象的时候分配一块内存空间,这块被分配给任务或者对象的空间叫做“栈”。栈的大小可以在创建任务的时候配置。每个栈都包含“Task File”和“Task Control Board(TCB)”,它们被内核用来处理任务。所有的Stack被存储在被称之为“堆”(HEAP)的结构里。堆管理器是依据Heap_x.c这个内核文件的内容来完成的,到底选择哪一个Heap_x.c是由需求决定的。
l Heap_1.c:最简单的实现,并且在分配完内存以后,不能释放。
l Heap_2.c:使用了“最佳适应”算法,允许之前分配的内存被回收。
l Heap_3.c:封装了标准的C函数malloc()和free(),在大多数情况下,可以被选用的C编译器支持。封装使得malloc和free函数的使用是线程安全的。
l Heap_4.c: 使用了“第一适应”算法,和heap_2.c不同的是,它可以将临皆被释放的内存融合成一个大的内存块。
除了Heap_3.c以外的所有模型都可以通过“configTOTAL_HEAP_SIZE”来配置,而Heap_3.c的堆大小配置则是通过链接器脚本来完成的。
2、开发板和调试器
本次实验采用了市面上较为常见的Cortex处理器开发板Arduino Due,其微控制器为AtmelSAM3X8E,跟踪和调试器采用了JLink Lite,如下图:
图 Arduino Due开发板和Jlink Lite
未完待续…