Andrew Huang bluedrum@163.com
一.关于FreeRTOS
FreeRTOS的一个开源实时操作系统,类似于uCOS/VxWorks.但是有几个特点是,uCOS是开源但是商用要收费。而FreeRTOS不但开源,商用也完全不受限制。另外一个是整个操作系统的核心只有四个C源代码和一些头文件,实在是出出乎人的意料.因此可以在更为简单的硬件环境下运行FreeRTOS,象ARM7之类没有MMU的CPU,还包括大部分OS不能运行的单片机环境。因此很多人开始用这个OS.
另有人提到,freertos 支持任务优先调度,并且同一优先级任务支持时间片轮番调度, ucos不支持时间片轮番调度。 freertos 任务数不受限制,最小RAM<400 byte ,rom < 4 kbyte, 优点:简单,轻小,简明,免费,升级快。
接触这个OS的原因是在一家大公司的做嵌入式C实时编程,对方提到自己原来一直是在单片机用FreeRTOS,因此想结合一下这个OS讲一下。了解FreeRTOS发现也相当简单,但是我手头都是S3C2440的板,但官方在ARM9下只有AT91的版本。而且是针对RVDS的。因此动了念头在用ADS移植FreeRTOS到S3C2440的念头。
二.FreeRTOS框架
FreeRTOS的官方网站是 http://www.freertos.org/,我使用是目前最新一个版本 6.0.5 http://sourceforge.net/project/showfiles.php?group_id=111543&package_id=120544
国内也有网站将其文档翻译成中文 www.openrtos.cn
用source insight 简单的查看各个源码和代码,以及demo的代码,基本上可以分析出如下结果。
2.1 内核代码
FreeRTOS的内核代码是croutine.c list.c queue.c tasks.c,头文件在include下.其中list.c,queue.c是实际上两种数据结构链表和队列的操作代码。这样内核代码实际上tasks.c和croutine.c. 其中tasks.c是用实时操作系统常见的Task的概念,或者是一般大型OS中的线程概念。每个Task的堆栈是独立的。而croutine.c描述是一种更为节约的任务模型,共享堆栈的任务模式。这样跟task.c是并行的代码。这样一个OS内核实际上只有一个C源代码实现的!!,tasks.c也不大,只有2300多行。croutine.c更小了,只有 360多行。
2.2 OS操作硬件代码
操作系统操作具体的CPU的硬件代码在portable目录,是按编译器类型来划分的,如GCC,RVDS(即ADS的升级版)
在某一个编译器下,又有具体CPU的控制代码。比如像这个 E:\FreeRTOS\Source\portable\GCC\ARM7_AT91SAM7S。每个CPU操作代码必须要实现 portmacro.h 和port.c 两个代码。这就是大部分的OS所说的BSP代码了。
2.3 完整target源码
有底层开发经验的工程师都知道,一个程序想在CPU上运行起来。还有一个最重要代码,就是汇编写的引导代码,以及操作系统的调用代码。FreeRTOS是把这一部分代码放在Demo目录,你可以看不同开发板的代码。引导代码就写在这里,象LPC2106代码就写在Demo/ARM7_LPC2106_GCC,在这个目录下我们能清楚看到boot.s.
从这一些源码来分析,FreeRTOS对这一些代码没有什么规定,前提只求在这个一些代码要有一个名为 main()的函数把操作系统调起来。一般调用象上例中的调用OS的代码是main.c中的main().从代码可以看到,都在创建一些Task(),最后进行OS的调度循环。
从它的Makefile中,我们可以看到,完整的代码还要链接2.1 /2.2 的相关代码。
这里是ARM9用IAR编译器的目录结构
从上述分析的我们得出两个结论。
一个在确定target运行的完整代码需要三大块源码 2.1 /2.2/2.3
在一个新的target移植FreeRTOS需要增加两块代码,一是在Portable目录下增加相应的OS操作硬件代码。第一个是在demo目录下增加相应引导代码。
2.4 第三方项目源码
在demo/common 目录下,放着FreeRTOS已经成功移植第3方项目,象uIP/lwIP/FatFs 等,在你的项目里可以考虑引入这一些源码。在很多项目还移植httpd来作为嵌入式服务器。这一些在未来都可以用来参考的。
关于移植FreeRTOS,动手前最好阅读一下官方网站这一篇文章
<<porting a freertos demo to different hardware>>
三.移植到S3C2440设备上
下一步我着手在我手里的S3C2440板上移植了 FreeRTOS,相对于ARM新的 RealView,更习惯用ADS.而且我机器上只有安装ADS。因此准备用这个编译器来编译了。
按照其规范,我首先在Source\portable目录下建立了 ADS\ARM9_S3C2440目录。
然后在Demo目录下建立 ARM9_S3C2440_ADS目录.
3.1 创建自己的portable代码。
FreeRTOS主要实现 portmacro.h/port.c,可以参考一个ARM7的类似代码。最好从RVDS目录下选一个,因这两个工具很多基本是一样的,包括汇编语法。我选用的ARM7_LPC21xx作为模板.
经过检查,这一份代码基本是ADS类似的语法。象关中断,开中断都是用ARMCC的内部函数,__disable_irq(),__enable_irq();但是寄存器宏名字有较大的调整。
3.2 创建自己的Demo代码.
这个因FreeRTOS对于相互的格式并无太多要求。把S3C2440的测试代码的引导代码拿过来即可。但是需要调整对于内存分区的相应代码,因为FreeRTOS也要用这一部分。
可以参考DEMO/ARM7_LPC2129_Keil_RVDS这一部分代码来调整。
我是把原来上课测试的LED测试代码直接搬过来的.
一编译有大量错误。因为我LED代码是测试工作正常。因此我觉得变换一下移植策略.即在已经运行成功的代码上没断调整变成符合RTOS API的代码。这样好处是我不断看到成功的结果,并能滚动开发。
3.3 第一次移植,调整LED控制代码
在很多demo项目下有ParTest.c 用于GPIO口的一些应用测试,包括LED测试。这一些代码跟内核并无太多关联,但是为了方便以后的开发者。可以在没有移植内核前先把这一些API函数移植了,作为第一步。
参见Demo/common/ParTest.h,主要实现如下三个函数
void vParTestInitialise( void ); //初始化
//
void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ); void vParTestToggleLED( unsigned portBASE_TYPE uxLED ); 3.3 时间频率及时间中断处理
这里有一些宏的值是要根据target来设置的.主要在FreeRtosConfig.h当中。
#define configCPU_CLOCK_HZ ( ( unsigned long ) BOARD_MCK )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) 时间中断在实时的OS起核心的调度作用,必须一启动OS时就要配置时间中断,相应代码在 port.c::prvSetupTimerInterrupt(); 3.4 内存分区设定
<<在线编写中>>
(Andrew Huang) |