一、
RT-Thread与UCOS的简单比较
任务或线程调度
RT-Thread可选优先级抢占式调度,256/32/8个优先级,线程数不限。相同优先级线程时间片轮转调度。支持动态创建/销毁线程。
Ucos优先级抢占式调度。不允许相同优先级任务存在。256个优先级,最大256个任务。
FreeRTOS优先级抢占式调度,允许存在相同优先级线程。任务数不受限制。
同步/通信机制:
RT-Thread支持semaphore、mutex、mailbox、message queue、event。mailbox可存储多条消息,任务等待可按照优先级进行排队。
UCOS信号量、互斥量、事件集、邮箱(邮箱最多只能存放一条消息),消息队列。
FreeRTOS信号量、互斥量、消息队列。
内存管理:
RT-Thread固定分区内存管理,小内存系统动态内存管理,大内存系统SLAB内存管理。
FreeRTOS动态内存。
UCOS固定大小内存管理。
定时器:
RT-Thread挂接到系统OS定时器的硬件定时器。
FreeRTOS依赖vTaskDelat()进行时间间隔处理。
UCOS只能使用OSTimeDly进行时间间隔处理。
中断嵌套:
RT-Thread–允许
FreeRTOS-允许
UCOS –不允许
二、RT-Thread的优点
RT-Thread是由中国开源社区主导开发的开源实时操作系统。它的优点是精巧、高效、稳定的实时内核。
三、使用RT-Thread开发的理由
免费开源
精巧、稳定、高效的实时内核,同时也是经过产品考核的实时内核。
由国内一批技术功底深厚的开发者进行维护
该系统支持ARM Cortex-M3系统移植分支尤其对STM32提供了功能齐全的BSP开发包。实现驱动包括:串口、网络、SD卡、USB接口等;支持所有系统组件:基本系统、TCP/IP协议栈。文件系统、图形界面。
开发周期短,采用STM32芯片、稳定性高、实时性高。健壮、高效、可靠性高、实时性强。提供丰富的驱动。
四、使用多线程平台进行开发的要点
1、“多线程”:RT-Thread操作系统是基于多线程的实时操作系统。线程是RT-Thread的线程管理是进行下一步开发的基础。
2、以对象的编程思想使用C语言:RT-Thread实时操作系统中包含一个小型的、非常紧凑的对象系统。这个对象系统完全采用C语言。
3、熟练使用RealView MDK420编译调试平台、不同容量的STM32处理器需要进行一些相应的配置的改动。
五、RT-Thread结构组成
在运行RT-Thread之前,我们需要安装RealView MDK(正式版或评估版)4.2+,它不仅是软件仿真工具也是编译器连接工具。
/*************************************************************************************************************************/
文章将采用连载的形式,从内核线程、线程间各种通信机制、各种组件的使用等方面一 一做介绍。另外文章主要讲解 RT-thread 的相关使用方法,即如何应用,而不是分析RT-thread 的内部具体实现机制。
硬件平台
后续例子中所牵扯到的软硬件实验环境如下: 操作系统:Windows XP SP3 开发编译环境:Keil MDK 4.54 版
对应硬件平台: stm32 RT_thread 综合实验平台 仿真器:STlink
RT-thread 版本:1.1.0 版 如果读者使用别的硬件平台,请稍改下里面的源码,使之与自己的目标板对应。
第一篇:认识 RT-thread
日期:2013-03-02
RT-thread 简介
RT-Thread(实时线程操作系统)是国内 RT-Thread 工作室精心打造的稳定的开源实时 操作系统,“她”是 RTT 核心成员历时 4 年,呕心沥血研发,力图突破国内没有小型稳定的 开源实时操作系统局面的开山之作,曾获得“第六届中日韩开源软件竞赛”技术优胜奖(其 他两个技术优胜奖获得者为淘宝的 OceanBase 和红旗的 Qomo Linux)
它不仅仅是一款开源 意义的硬实时操作系统
(不是软的哦),也是一款产品级别的实时操作系统,目前已经被国 内十多家企业采用,被证明是一款能够稳定持续运行的操作系统。
RT-Thread 实时操作系统核心是一个高效的硬实时核心,它具备非常优异的实时性、稳 定性、可剪裁性,当进行最小配置时,内核体积可以到 3k ROM 占用、1k RAM 占用。目前 RT-thread 支持的分支和包含的组件如下:
分支:
-
ARM Cortex-M3: STM32F1, STM32F2, LPC176xx, LPC18xx, LM3S, EFM32, MB9BF
-
ARM Cortex-M4: STM32F4, LM4S, LPC4300
-
ARM7TDMI: LPC2478, LPC2148, AT91SAM7S, AT91SAM7X, S3C44B0
-
ARM720T: SEP4020
-
ARM9: AT91SAM9260, S3C2440
-
NIOS-II
-
XILINX MicroBlaze
-
AVR32
-
Blackfin 533
-
MIPS: PIC32, Jz47xx
-
PPC450: taihu
-
x86
-
windows simulator (VC++)
组件
-
CMSIS, CMSIS-RTOS
-
RT-Thread DFS 文件系统:devfs, ELM FatFs, JFFS2, NFS, romfs, UFFS, YAFFS2
-
finsh shell (类似命令行的组件,RTT 的亮点哦)
-
libc: armlibc(针对 Keil MDK), newlib
-
POSIX: pthreads, libdl
-
网络:lwIP 1.4.0
-
RT-Thread GUI
-
lua
-
Device Drivers: IIC, MTD NOR/NAND, RTC, SDIO, serial, SPI Bus/Device, USB device/host
RT-thread 授权
我们使用操作系统,应该都会考虑一个收费问题,使用 RT-thread,我们就不用担心这 个问题了。RT-Thread 采用 GPL-V2 发布,并且承诺永久不会针对使用 RT-Thread 收费,用 户只需要保留 RT-Thread 的 LOGO 既可以免费使用。
下载 RT-thread 源码、资料
RT-thread 最新稳定版是 1.1.0 版,我们可登陆 RT-thread 官方网站
http://www.rt-thread.org
,点击如下图中红色框中的超链接进行下载,同时也可以下载到其 编程指南。
RT-thread 工作室人员除了进行 RT-thread 操作系统及其组件的开发维护外,还主导了 一些较大开源的软硬件项目,这些项目在其论坛中都可以找得到,也可以跟着这些开源项目 去深入学习 RT-thread 的使用。
第二篇 感受 RT-thread
日期:2013-03-12
RT-thread 源码目录结构介绍 解压源码后,会看到如下的文件和文件夹:
接下来简单说说各文件夹、文件的作用。 Bsp — 包含 RT-thread 的各个移植分支;
components — 包含 RT-thread 的各中组件:finsh、文件系统、网路协议栈等;
documentation — 一些介绍性的文档,包括其代码风格的要求;
examples — 各种示例代码,是很好的学习素材;
include — 一些头文件;
libcpu — 各种 CPU 体系结构下的相关移植; src — RT-thread 内核核心代码;
tools — 使用 scon 工具编译时的一些相关文件;
AUTHORS — RT-thread 开发者列表
COPYING — 权限说明
第一次运行 RT-thread
RT-thread 成员已经为我们做好了各种平台下的移植,我们打开 bsp 目录下,stm32f10X 系列的对应分支,双击 MDK 下工程 project.Uv2,打开工程。
这个示例工程包含了 RT-thread 的内核、finsh 组件这两个最基本的部分,主代码完成 了从 RT-thread 的启动到创建一个闪灯线程的过程,程序运行时会通过串口打印运行信息。 我们根据目标板上的 LED 和串口引脚对应关系修改一下程序。
目标板 LED、串口电路如下:
led.c 中我们用 GPIOF8、GPIOF9 来替换原来的 GPIOE2、GPIOE3:
程序中默认使用串口 1 作为终端,针对我的目标板就无需改了,如果你的板子串口不是 串口 1,则改动下面两处:
board.h 中:
rt_config.h 中:
编译后下载到目标板运行,我们会看到 D5 LED 灯以 1Hz 的频率闪烁,同时串口输出了 系统启动信息:
OK,到这里,RT-Thread 就算是在我们的目标板上正常的运行起来了,是不是很简单呢? 赶紧试试吧,心动不如行动!
第三篇 搭建 RTT 最小系统工程
日期:2013-03-24
建立自己的 RT-Thread 工程
为了后续增加例程方便,我重新生成了一个工程,见《篇 3-例程 1-重构 RTT 最小系统》, 这个工程提取了官方 bsp 包中 stm32 分支中的相 关文件,重新组织文件结构,按照下图中 的文件分配,重新生成了工程。
project ——存放 MDK 工程文件;
RT-thread ——存放 rtt 源码包(放在最外层);
apps ——存放我们自己(用户)写的一些应用代码; drivers ——存放硬件外设驱动;
third_part ——存放第三方程序源码,比如 stm32 固件库、解码库等; obj ——目标文件;
这么一来,各类代码分类一清二楚,后续的例程都会按照这种格式去处理。 例程将闪灯功能换成了流水灯功能,MDK 下文件目录如下图:
RT-Thread 启动过程
我们分析一个系统的启动过程,一般都从 main 函数开始,我们点开 startup.c 找到 main 函数,main 函数就下面 3 行:
第一行是关中断的操作,第三行是返回退出(永远都执行不到),那么看来 Rt-Thread 的启动就在第二行中进行的,我们贴上 rtthread_startup()的内容来大致浏览一下其启动过 程:
上面的函数完成了系统启动前的所有初始化动作,包括必要的硬件初始化、堆栈初始化、 系统相关组件初始化、用户应用程序初始化,然后启动调度机制。其中和用户密切想关的就 是 rt_application_init()函数,用户线程的创建入口就在这个函数中(此函数函数名用户可 自定义)。
RT-Thread 的裁剪
我们在上面的启动函数中看到了如下的一些宏定义:
这些宏定义就是为了 RT-Thread 的可裁剪性而做的,对于其裁剪配置,我们在 rt_config.h 中进行,每个配置项的详细解释,请参考配置项上的英文解释和《RT-Thread 编 程指南》。我们在应用过程中,要根据实际的使用情况来选择打开或屏蔽掉某些功能。
第四篇 线程基本知识
日期:2013-03-24
什么叫线程?
人们在生活中处理复杂问题时,惯用的方法就是“分而治之”,即把一个大问题分解成 多个相对简单、比较容易解决的小问题,小问题逐个被解决了,大问题也就随之解决了。同 样,在设计一个较为复杂的应用程序时,也通常把一个大型任务分解成多个小任务,然后通 过运行这些小任务,最终达到完成大任务的目的。
在 RT-Thread 中,与上述小任务对应的程序实体就叫做“线程”(或任务),RT-Thread 就是一个能对这些小“线程”进行管理和调度的多“线程”操作系统。
线程的组成
RT-Thread 中的“线程”一般由三部分组成:线程代码(函数)、线程控制块、线程堆栈,我们来看看《篇 3-例程 1-重构 RTT 最小系统》中的流水灯线程是如何构造的。
线程代码:
上面即是一个典型的线程代码结构—无限死循环,当然还有一种线程结构是顺序执行的, 比如初始化线程,它执行到 return(),就会返回,当其返回后,系统会在 idle 线程中将 其删除,从而使其退出调度队列。一般情况下用户线程都将是一个无限循环结构。
线程控制块:
static struct rt_thread led_thread;
其中线程控制块 rt_thread 结构体具体内容如下:
struct rt_thread
{
/* rt object */
char name[RT_NAME_MAX]; /
< the name of thread */
rt_uint8_t type; /
< type of object */
rt_uint8_t flags; /**< thread’s flags */
#ifdef RT_USING_MODULE
void *module_id; /**< id of application module */
#endif
rt_list_t list; /
< the object list */
rt_list_t tlist; /
< the thread list */
/* stack point and entry */
void *sp; /
< stack point */
void *entry; /
< entry */
void *parameter; /
< parameter */
void *stack_addr; /
< stack address */
rt_uint16_t stack_size; /**< stack size */
/* error code */
rt_err_t error; /**< error code */
rt_uint8_t stat; /**< thread stat */
/* priority */
rt_uint8_t current_priority; /
< current priority */
rt_uint8_t init_priority; /
< initialized priority */
#if RT_THREAD_PRIORITY_MAX > 32
rt_uint8_t number; rt_uint8_t high_mask;
#endif
rt_uint32_t number_mask;
#if defined(RT_USING_EVENT)
/* thread event */ rt_uint32_t event_set; rt_uint8_t event_info;
#endif
rt_ubase_t init_tick; /**< thread’s initialized tick */
UP MCU 工作室 14 / 17
http://shop73275611.taobao.com/
它记录了线程的各个属性,系统用线程控制块链表对其进行管理
线程堆栈:
static rt_uint8_t led_stack[ 512];
线程堆栈是一段连续的内存块,当线程切换后,为了满足线程切换和响应中断时保存 cpu 寄存器中的内容及任务调用其它函数时的准备,每个线程都要配有自己的堆栈
创建一个我们自己的线程 前面说了这么多,我们还是来自己建立一个线程,这样的话印象更深刻。
RT-Thread 中的线程分为静态线程(线程堆栈由编译器静态分配)和动态线程(线程堆 栈由系统动态分配),在例程《篇 4-例程 1-自己创建静态、动态线程》中我们分别建立一 个静态线程和动态线程,这两个线程的任务都是使板上的 LED 灯以 1Hz 频率闪烁。
编译此例程下载到板子中运行,我们看到 D3、D4 灯以同样的节奏闪烁,同时串口也打 印出了如下的运行信息: