FreeRTOS与uCOS II的比较(嵌入式实时系统)

目前嵌入式主流实时系统(RTOS)有uCOS、FreeRTOS,之所以很多第三方库都有在FreeRTOS上的应用Demo,是因为FreeRTOS免费。不要钱是真的厉害呀!然而说实话,论源码规范,我还是喜欢uCOS。

一、FreeRTOS比uCOS II优胜的地方:
1。内核ROM和耗费RAM都比uCOS 小,特别是RAM。 这在单片机里面是稀缺资源,uCOS至少要5K以上, 而FreeRTOS用2~3K也可以跑的很好。

2。FreeRTOS 可以用协程(Co-routine),减少RAM消耗(共用STACK)。uCOS只能用任务(TASK,每个任务有一个独立的STACK)。

3。FreeRTOS 可以有优先度一样的任务,这些任务是按时间片来轮流处理,uCOSII 每个任务都只有一个独一无二的优先级。因此,理论上讲,FreeRTOS 可以管理超过64个任务,而uCOS只能管理64个。

4。FreeRTOS 是在商业上免费应用。uCOS在商业上的应用是要付钱的。

二、freeRTOS 不如uCOS的地方:
1。比uSOS简单,任务间通讯FreeRTOS只支持Queque, Semaphores, Mutex。 uCOS除这些外,还支持Flag, MailBox.

2。uCOS的支持比FreeRTOS 多。除操作系统外,FreeRTOS只支持TCPIP, uCOS则有大量外延支持,比如FS, USB, GUI, CAN等的支持

3。uCOS可靠性更高,而且耐优化,FreeRTOS 在我设置成中等优化的时候,就会出问题。

关于移植FreeRTOS进入其他开发板的问题,可以参考朱工的博客
https://blog.csdn.net/zhzht19861011/article/category/9265276

后记
早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。 简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。


这里就是平时我们裸机的运行结果,现在比如我在运行task3,突然又想马上运行task1,这怎么办?前后台程序就会让后面的任务执行之后,再去执行task1,这样实时性受到影响。如果是裸机,要实现也可以,用中断,可是这样会让程序结构变得复杂,因为我想什么时候跳过就跳过,想什么时候执行就执行,所以固定的中断触发方式虽然也可以实现一些简单的跳转功能,但是当程序复杂之后,这样的裸机程序难以阅读和维护。这样在有操作系统的任务调度之后,就会让系统响应更具有实时性。

RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。

实时操作系统又分为硬实时和软实时。硬实时要求在规定的时间内必须完成操作 ,硬实时系统不允许超时,在软实时里面处理过程超时的后果就没有那么严格。

在实时操作系统中,我们可以把要实现的功能划分为多个任务,每个任务负责实现其中的一部分,每个任务都是一个很简单的程序,通常是一个死循环。 RTOS操作系统:FreeRTOS,UCOS,RTX,RT-Thread,DJYOS等。 RTOS操作系统的核心内容在于:实时内核。

可剥夺型内核:

RTOS的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其他任务,这个是内核的多任务管理能力。多任务管理给人的感觉就好像芯片有多个CPU,多任务管理实现了CPU资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时应用。

可剥夺内核顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。


FreeRTOS是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。FreeRTOS提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。 FreeRTOS是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的,FreeRTOS结构简洁,可读性很强!最主要的是非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。

为什么需要学习这个操作系统:


高级后记
uC/OS-III和FreeRTOS的区别

在阅读完uC/OS-III(V3.03.01)和FreeRTOS(V10.0.1)的源码后,我对RTOS有了较深的认识。现将它们之间的一些区别总结出来,有利于大家理解这两个RTOS。

1、uCOS-III中所有的内核对象(如任务控制块、消息队列、信号量等)都是静态创建的,需要用户提供。FreeRTOS中的内核对象支持动态和静态两种创建方法。
(PS: 其实系统提不提供动态创建功能并不那么重要,因为在静态创建的方法的基础上加入内存管理机制,就能自已封装实现动态创建函数)

2、uCOS-III中的任务状态较多,因为它存在“基本状态+挂起状态”这类状态,FreeRTOS中挂起态是个单独的状态。在FreeRTOS中,如果suspend一个正在阻塞的任务,API内部会把任务从相应阻塞表中删除,并将其挂在xSuspendedTaskList上,当该任务被resume后,它就是就绪态,而不会重新返回阻塞态。而uCOS-III中的任务即便在阻塞时被suspend了,它依然处于阻塞态(即等待某个事件发生),如果在suspend的过程中事件发生了,它将解除阻塞态,变为纯粹的挂起态;如果在resume后,该事件仍未发生,它将解除挂起态,变为阻塞态。
(PS: 我感觉uCOS-III中的“挂起”更能称之为“挂起”)

3、为了实现中断和任务的同步,需要在中断中进行post操作,uC/OS-III为了减少中断执行的时间,提高系统中断响应的实时性,设计了OS_tickTask和OS_IntQTask,这样原本在中断里需要进行的一些较为耗时的操作就被放到了任务级代码中执行了。而FreeRTOS并没有这样的设计。
(PS: 我觉得,从这一点上,可以看出uC/OS-III的实时性要比FreeRTOS好。
另外,可能有的同学不理解为什么中断执行时间少了,系统的实时性就好了。这是因为系统实时性的一个关键指标就是中断延迟响应的时间。某个中断可能会被延迟响应的时间,受系统关中断时间的影响,也会受其它同等优先级或者高优先级中断执行时间的影响,所以减少某个中断的执行时间,将有助于减少其它中断的延迟响应时间)

4、uC/OS-III和FreeRTOS的任务切换都是利用的PendSV中断。
在FreeRTOS的PendSV中断中,它会计算就绪的最高优先级的任务,再去进行上下文切换。而uC/OS-III在触发PendSV中断前,会计算好已就绪的最高优先级的任务,放在OSTCBHighRdyPtr中,这样在PendSV中断中就不用计算就绪的最高优先级的任务是谁了。所以uC/OS-III中PendSV中断的执行时间更短,这有利于提高系统的实时性。

5、uCOS-III的任务操作句柄就是任务控制块TCB的指针。FreeRTOS中单独设置了任务操作句柄这种数据类型,它实质上也是TCB的指针。表面上看,多此一举,但其实这种设计对用户是友好的,用户不需要了解TCB这种内核数据结构的存在,就可以操作任务了。

6、对于时间片轮转调度的功能。
FreeRTOS是每个时间片(即每个systick中断里)发生同优先级的任务切换。
而uCOS-III中每个任务能保持的时间片可以单独设置,需要在任务初始化时作为形参传入。这样做的坏处是对用户不太友好(API的形参如果太多,应用开发人员接受起来有些麻烦);这样做的好处是不会在每个时间片都发生任务的切换(任务切换是需要开销的),提高了总的CPU利用率。
另外,uC/OS-III中,由于可以对每个任务的时间片分别进行设置和修改,所以可以很方便地调节同优先级下每个任务的CPU占用率,尽管两个任务的优先级是一样的,但是有个任务比较重要,我们希望让它的CPU占用率高一点,这时只要把它的时间片设置得大一点即可。而在FreeRTOS中同优先级下的每个任务对CPU的占用率都只能是一样的。

7、uCOS-III内核中的链表大多是不循环的双向链表(有头有尾),在插入和删除操作时,要考虑特殊情况(比如插入表头、插入表尾等特殊情况)。
而FreeRTOS内核中的链表为双向循环链表,并引入了xListEnd保证了链表永远非空,所以每个元素的插入和删除都是作为表中的一般元素(非表头和表尾)进行的,操作效率要比uC/OS-III高一些。

8、对于修改任务优先级的操作,FreeRTOS和uCOS-III都是可选项。
对于uCOS-III,在修改任务优先级时,如果任务处于阻塞态,内核会将pend_data从阻塞对象的pend_list上删除,并重新按照新的任务优先级插入,即调用OS_PendListInsertPrio()。
而FreeRTOS对于修改阻塞态的任务的优先级,似乎只是修改了TCB里的优先级字段就完事儿了,这点虽然不会造成较大的影响,但是违背了“优先级高的任务优先获得阻塞对象”的设计原则。不知这是否是bug。

9、uCOS-III的信号量是没有上限的,只要post,它的信号量值就会增加(不能溢出)。而FreeRTOS中的信号量基于Queue_t实现,其队列容量(uxLength)将作为信号量的上限。

10、uCOS-III支持PendAbort,而FreeRTOS不支持。

11、uCOS-III中的软件定时器是靠对systick分频实现的,与OS_TickTask运行原理类似,都采用的哈希散列表组织定时器。
FreeRTOS中的定时器是按照超时时间组织成了有序链表。prvTimerTask与LwIP中的tcpip_thread一样,每次都试图按照当前超时链表上的最近超时时间阻塞在queue上。
FreeRTOS的定时器机制,单独设计了一个queue,所有Timer相关的API(函数或宏)本质上都是对该queue的一次消息投递,由prvTimerTask来完成对消息的解析并处理。这样做的好处就是:只在一个线程中进行与Timer相关数据的操作,省去了互斥带来的开销。

13、uCOS-III的许多API,都设计了OS_ERR* 的参量,它可以用来向应用程序传递许多出错信息,虽然这会增加API的复杂度,给应用程序开发人员带来一些麻烦。比如OSQueuePend,通过&err,我们可以知道这次pend操作是成功还是失败的,如果失败,是怎么失败的(比如:超时、队列被删除、队列被PendAbort等)。有的人可能会说,只要观察函数返回值,就可以知道此次pend操作时成功还是失败的,没必要设置OS_ERR* 这个参量。但是这样做无法得知失败的具体原因。
FreeRTOS在设计API时就没有设计这个错误参量,应用程序开发人员只能通过API函数的返回值来判断操作是否成功,但是如果失败,则无法得到更多的关于失败的信息。
(PS: 从这一点上可以看出,uC/OS-III提供了更健壮的内核)

14、对于消息队列,uCOS-III只支持出队阻塞,不支持入队阻塞,即OSQueuePost这个函数在消息队列已满的情况下,不会自已阻塞去等待队列里腾出空间,而是直接返回邮箱已满的错误信息,用户需要及时检查返回的错误码,进行处理。
FreeRTOS中即支持出队阻塞,也支持入队阻塞。
(PS: 在uC/OS-III中尽管不支持post阻塞,但如果必须实现post阻塞(比如LwIP移植中的sys_arch_mbox_post接口实现)也是很容易的,只要利用信号量和消息队列再加上一个阻塞队列专门用来记录等待post的任务即可,这是对uC/OS-III内核进行二次开发)。

15、uC/OS-III使用消息指针代表消息,FreeRTOS使用消息内容的完整备份代表消息,在uC/OS-III中,投递了消息以后,要保证该指针在消息被利用前一直有效(即保证消息内容不被删除、覆盖),在FreeRTOS中则无所谓,另外在FreeRTOS中也可以将消息指针当做消息内容传递,这样就可以模拟出跟uC/OS-III一样的效果了。
如此看来,FreeRTOS的消息设计更加灵活。但是要注意,使用指针的好处是避免消息的拷贝,这可以提高内核的处理效率,尤其是消息内容较大或者消息需要辗转多个消息队列的时候。所以我觉得像uC/OS-III这样设计就挺好的,没必要考虑其他情况。另外,uC/OS-III的消息是以OS_MSG结构体存在的,里面除了消息指针以外,还包含了时间戳,提供了更丰富的信息。不过要注意,由于它使用了OS_MSG结构体承载消息,而OSQueuePost函数内部是通过预先定义好的OS_MSG结构体内存池去获取这种结构的,所以需要用户在编译工程代码时根据自己使用到的消息的规模去配置内存池大小,一些人以为从uC/OS-II过渡到uC/OS-III的好处就是再也不用事先配置每种内存池的大小了(当应用需求变化,总是需要调整,比较麻烦),但千万别忘了有一个(也是唯一一个)内存池需要提前配置好大小。

16、在消息投递时,如果有任务在消息队列的pend列表中等待,uC/OS-III的做法是直接将该消息post给等待的任务并把它就绪,整个消息不会经过消息队列。而FreeRTOS的做法是将该消息放置到消息队列中,然后检查是否有任务正等待接收消息,如果有,就将其就绪,由就绪的任务去主动获取该消息。
FreeRTOS的做法实现了投递消息与取出消息的解耦,但这带来了一个问题,就是当某个任务投递完一个消息,并使A任务就绪了,而在A任务执行前,又有一个高优先级的B任务从这个消息队列中取出了该消息,那么A任务在以后试图从消息队列中取出消息时,会出现失败,这是FreeRTOS中所有内核对象的pend操作都可能会出现的情况,内核的做法是会重新计算超时时间,只要没超时,就重新阻塞(按新的阻塞时间),这种设计会降低内核的执行效率。在uC/OS-III中,每一次的消息post操作,要么消息被post到了消息队列上,要么消息被post给了任务,操作结果是明确的,操作过程是高效的。
(PS: 我觉得,从这一点可以看出uC/OS-III的内核要比FreeRTOS具有更好的效率、行为可预测性)

17、uCOS-III的pend函数用opt字段区分是try pend还是block pend,如果是block pend,可设置超时时间,如果超时时间为0,则代表永久pend。
FreeRTOS的pend函数没有opt字段,只有超时字段,如果它为0,则表示不等待,为try pend,如果为其他值,则它为超时时间,如果它为最大值(portMAX_DELAY),并且配置文件中使能了suspend task的功能,则portMAX_DELAY表示永久等待,如果没使能,则表示portMAX_DELAY个ticks将作为超时时间。
可见FreeRTOS中,在不使能task suspend的情况下,是不允许有任务永久阻塞的(可能是为了应用程序的安全性考虑)。

18、FreeRTOS提供了TaskNotIFy机制,用它可以更轻便地实现:单对单或多对单的简单同步和通信功能。在uC/OS-III中虽然没有TaskNotify机制,但是提供了TaskSem和TaskQueue机制,可以完成同样的效果。
(PS: 为了跨系统的可移植性,最好不要使用这些特殊机制)

总结:FreeRTOS功能更丰富、更易用;uC/OS-III的实时性更好、效率更高、健壮性更好。
其实RTOS最主要的功能就是任务调度,其它功能都可以自己开发,难度不大。单独从任务调度器的角色出发去对比这两个RTOS,我觉得uC/OS-III更漂亮、更优秀。

uC/OS-III通过的安全认证比FreeRTOS要多,FreeRTOS的代码书写是不符合一些标准的。在FreeRTOS的基础上建立了另外两个RTOS:SafeRTOS、OpenRTOS,它们具有更好的安全性,通过了更多的检验和标准,但是与FreeRTOS不一样,需要收费。

在过去EETimes的RTOS市场占有率调查中,FreeRTOS常年稳居第一,这与它完全免费、开源社区比较活跃的特点有关。再加上FreeRTOS的创始团队现在与亚马逊合作,FreeRTOS的系统功能将更加丰富,将拥有更多商业合作伙伴,用户数量群将继续扩大,目测FreeRTOS的发展前景会更好。

参考:[FreeRTOS与uCOS II的比较(嵌入式实时系统)](https://blog.csdn.net/qq_38769551/article/details/102838994)

原文链接:https://blog.csdn.net/weixin_43684318/article/details/120465717

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值